Swift 图标框架: Charts 入门教程

Charts 框架是 Apple 在 2022 年新增加的框架。通过该框架,你可以用最少的代码来构建高效、自定制的图表。该框架提供标记、比例、轴和图例作为构建块,你可以将它们组合起来开发各种数据驱动的图表。

下图是官方文档的示例图片:

通过上图可以看到,我们可以通过 Charts 创建各种图标:折线图、柱状图、散点图等。而且该框架会根据数据自动生成合适的外观。

废话不多说,开始编码时间。

简单使用

假设我们有这样一个需求:需要用柱状图展示天津周一到周三的温度。

首先,导入 Charts。然后,定义一个结构体用来表示数据,定义一个数组用来存储数据。

kotlin 复制代码
struct Temperature: Identifiable {
    let weekday: String
    let data: Double
    
    var id: String { weekday }
}

let tj_temperatures: [Temperature] = [
    .init(weekday: "周一", data: 33.8),
    .init(weekday: "周二", data: 32.6),
    .init(weekday: "周三", data: 30)
]

接着,就是在 Charts 里面填充数据就可以了:

css 复制代码
struct ContentView: View {
    var body: some View {
        VStack {
            Text("天津温度表")
            Chart {
                ForEach(tj_temperatures) { temperature in
                    BarMark(x: .value("day", temperature.weekday), y: .value("temperature", temperature.data))
                }
            }
        }
    }
}

上述 .value 函数,第一个参数为当前轴代表的含义,第二个参数是具体数据。 效果图:

Tips:因为 Charts 的初始化函数的作用跟 ForEach 类似,所以上述代码可以简化成这样:

less 复制代码
Chart(tj_temperatures) {
    BarMark(x: .value("day", $0.weekday), y: .value("temperature", $0.data))
}

如何将柱状图改成折线图呢?只需改动一句代码即可:将 BarMark 替换为 LineMark。 下面是官方支持的几种 Mark:

  • AreaMark:区域图
  • LineMark:折线图
  • PointMark:散点图
  • RectangleMark:矩形图
  • RuleMark:使用单个水平或垂直规则表示数据的图表内容
  • BarMark:柱状图 具体样式可参见官方文档

动态切换

通过声明一个状态变量,可以根据状态变量的变化,来动态切换图标的数据。

首先定义一个枚举来区分地区,并定义地区的数据源:

php 复制代码
let tj_temperatures: [Temperature] = [
    .init(weekday: "周一", data: 33.8, city: "tj"),
    .init(weekday: "周二", data: 32.6, city: "tj"),
    .init(weekday: "周三", data: 30, city: "tj")
]

let bj_temperatures: [Temperature] = [
    .init(weekday: "周一", data: 36, city: "bj"),
    .init(weekday: "周二", data: 30, city: "bj"),
    .init(weekday: "周三", data: 34, city: "bj"),]

enum City {
    case tj
    case bj
}

接着,定义一个状态变量 city,用来保存当前的地区。声明一个 data 变量,保存相应的地区数据源:

java 复制代码
@State var city: City = .tj
    var data: [Temperature] {
        switch city {
        case .tj:
            return tj_temperatures
        case .bj:
            return bj_temperatures
        }
    }

最后,实现点击事件控件和 Charts:

scss 复制代码
var body: some View {
    VStack {
        Text("北京/天津温度表")
        Picker("city", selection: $city.animation(.easeInOut)) {
            Text("天津").tag(City.tj)
            Text("北京").tag(City.bj)
        }
        .pickerStyle(.segmented)
        Chart(data) {
            BarMark(x: .value("name", $0.weekday),
                    y: .value("length", $0.data))
        }
    }
}

Tips:Charts 也是支持 SwiftUI 的动画效果的。

两及多条线的折线图

如果我们需要进行多个数据的对比,比如展示天津、北京和河北的温度对比。可以使用 foregroundStyle 来进行实现。

首先,我们需要将三个地区的温度数据组成一个数组,并通过一个 city 的字段来区分地区:

php 复制代码
let total: [Temperature] = [
    .init(weekday: "周一", data: 36, city: "bj"),
    .init(weekday: "周二", data: 30, city: "bj"),
    .init(weekday: "周三", data: 34, city: "bj"),
    .init(weekday: "周一", data: 33.8, city: "tj"),
    .init(weekday: "周二", data: 32.6, city: "tj"),
    .init(weekday: "周三", data: 31, city: "tj"),
    .init(weekday: "周一", data: 34.8, city: "hb"),
    .init(weekday: "周二", data: 36.6, city: "hb"),
    .init(weekday: "周三", data: 28, city: "hb")
]

接着,调用 foregroundStyle(by: PlottableValue) 函数,将 city 字段值传进去即可:

css 复制代码
struct ContentView: View {
    var body: some View {
        VStack {
            Text("北京/天津/河北温度表")
            Chart(total) {
                LineMark(x: .value("name", $0.weekday), y: .value("length", $0.data))
                    .foregroundStyle(by: .value("city", $0.city))
            }
        }
    }
}

系统会自动给不同的地区分配不同的颜色,用来区分。示例图如下:

如果不想使用系统自动分配的颜色,也可以使用 chartForegroundStyleScale<Range>(range: Range, type: ScaleType? = nil) 函数来进行自定义。示例代码如下:

less 复制代码
let markColors: [Color] = [.black, .red, .cyan]
struct ContentView: View {
    var body: some View {
        VStack {
            Text("北京/天津/河北温度表")
            Chart(total) {
                LineMark(x: .value("name", $0.weekday), y: .value("length", $0.data))
                    .foregroundStyle(by: .value("city", $0.city))
            }
            .chartForegroundStyleScale(range: markColors)
        }
    }
}

结果如下:

横向的柱状图

对 Charts 来说,横向的柱状图也是非常简单的,将 x 轴与 y 轴的数据互换一下,我们就可以得到横向的柱状图了。

less 复制代码
Chart(total) {
    BarMark(x: .value("length", $0.data),
            y: .value("name", $0.weekday))
    .foregroundStyle(by: .value("city", $0.city))
}
相关推荐
专业开发者3 小时前
调试 iOS 蓝牙应用的新方法
物联网·macos·ios·cocoa
tangbin5830857 小时前
iOS Swift 可选值(Optional)详解
前端·ios
卷心菜加农炮20 小时前
基于Python的FastAPI后端开发框架如何使用PyInstaller 进行打包与部署
ios
北极象1 天前
千问大模型接入示例
ios·iphone·qwen
ipad协议开发1 天前
企业微信 iPad 协议应用机器人开发
ios·企业微信·ipad
QuantumLeap丶2 天前
《Flutter全栈开发实战指南:从零到高级》- 26 -持续集成与部署
android·flutter·ios
2501_915918412 天前
TCP 抓包分析在复杂网络问题中的作用,从连接和数据流层面理解系统异常行为
网络·网络协议·tcp/ip·ios·小程序·uni-app·iphone
二流小码农2 天前
鸿蒙开发:个人开发者如何使用华为账号登录
android·ios·harmonyos
wvy2 天前
Xcode 26还没有适配SceneDelegate的app建议尽早适配
ios
游戏开发爱好者82 天前
苹果 App 上架流程,结合 Xcode、CI 等常见工具
macos·ios·ci/cd·小程序·uni-app·iphone·xcode