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))
}
相关推荐
GitLqr6 小时前
iOS 27 强制要求 UISceneDelegate:UIKit 和 Flutter 开发者该如何应对?
flutter·ios·全栈
屑曦晨8 小时前
PKToolPicker工具栏图标错误模糊问题排查报告
ios
2501_915921439 小时前
详细解析,iOS 应用上架 App Store 的完整流程与指南
android·ios·小程序·https·uni-app·iphone·webview
2501_915106329 小时前
SwiftUI项目创建详解:使用Xcode从零开始创建第一个App项目
ide·vscode·ios·swiftui·个人开发·xcode·敏捷流程
97650333511 小时前
iOS 上架/审核 4.3a Cocos 2026最新方案解读
flutter·ios·swift·cocos2d·ios开发
2501_9160074711 小时前
IDE 是什么?集成开发环境详解与 iOS 开发选型指南
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
梦想的颜色12 小时前
UniApp 四端对齐实战:iOS App / Android App / 小程序 / H5 兼容坑点与完整解决方案|AI 辅助多端落地
android·ios·小程序·uni‑app·uniapp 四端适配·多端兼容·ai 生成 uni‑app
CocoaKier21 小时前
喜大普奔!2027年春季起,iOS提审最低支持iOS15.0以上
ios·apple
初级代码游戏1 天前
iOS开发 Swift 速记2:三种集合类型 Array Set Dictionary
开发语言·ios·swift
凡泰AI1 天前
APP同时覆盖了iOS、安卓和鸿蒙,如何选择混合开发架构才能减少重复建设,提高功能上线效率~
android·ios·harmonyos·mpaas·uni·小程序容器