在 iOS 16 中用 SwiftUI Charts 创建一个折线图

news2025/1/23 11:53:42

前言

苹果在 WWDC 2022 上推出了 SwiftUI 图表,这使得在 SwiftUI 视图中创建图表变得异常简单。图表是以丰富的格式呈现可视化数据的一种很好的方式,而且易于理解。本文展示了如何用比以前从头开始创建同样的折线图少得多的代码轻松创建折线图。此外,自定义图表的外观和感觉以及使图表中的信息易于访问也是非常容易的。

如以前的文章所示,不使用 SwiftUI Charts 也可以创建一个折线图。然而,使用 Charts 框架可以提供大量的图表来探索对应用程序中的数据最有效的方法,从而使它变得更加容易。

系列文章

  1. 如何在 SwiftUI 中创建条形图
  2. SwiftUI 中的水平条形图
  3. 在 iOS 16 中用 SwiftUI Charts 创建一个折线图
  4. 在 iOS16 中用 SwiftUI 图表定制一个线图
  5. 在 Swift 图表中使用 Foudation 库中的测量类型

简单折线图

从包含一周的步数的数据开始,类似于 在SwiftUI中创建折线图 中使用的数据。定义一个结构来保存日期和该日的步数,并为当前周创建一个数组。

struct StepCount: Identifiable {
    let id = UUID()
    let weekday: Date
    let steps: Int
    
    init(day: String, steps: Int) {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMdd"
        
        self.weekday = formatter.date(from: day) ?? Date.distantPast
        self.steps = steps
    }
}


let currentWeek: [StepCount] = [
    StepCount(day: "20220717", steps: 4200),
    StepCount(day: "20220718", steps: 15000),
    StepCount(day: "20220719", steps: 2800),
    StepCount(day: "20220720", steps: 10800),
    StepCount(day: "20220721", steps: 5300),
    StepCount(day: "20220722", steps: 10400),
    StepCount(day: "20220723", steps: 4000)
]

要创建一个折线图,为步数数据中的每个元素创建一个带有LineMark的图表。在LineMark的 X 值中指定工作日,在 Y 值中指定步数。注意,还需要导入Charts框架。

这就为步数数据创建了一个线形图。由于只有一个系列的数据,ForEach 可以省略,数据可以直接传递给 Chart 初始化器。两个部分都产生相同的折线图。

import SwiftUI
import Charts

struct LineChart1: View {
    var body: some View {
        VStack {
            GroupBox ( "Line Chart - Step Count") {
                Chart {
                    ForEach(currentWeek) {
                        LineMark(
                            x: .value("Week Day", $0.weekday, unit: .day),
                            y: .value("Step Count", $0.steps)
                        )
                    }
                }
            }
            
            GroupBox ( "Line Chart - Step Count") {
                Chart(currentWeek) {
                    LineMark(
                        x: .value("Week Day", $0.weekday, unit: .day),
                        y: .value("Step Count", $0.steps)
                    )
                    
                }
            }
        }
    }
}

使用 SwiftUI Charts 创建的折线图显示每日步数

使用 SwiftUI Charts 创建的折线图显示每日步数

其他图表

SwiftUI Charts 有许多可用的图表选项。这些可以通过将图表标记从LineMark改为其他类型的标记(如BarMark)来生成条形图。

struct OtherCharts: View {
    var body: some View {
        VStack {
            GroupBox ( "Line Chart - Step count") {
                Chart(currentWeek) {
                    LineMark(
                        x: .value("Week Day", $0.weekday, unit: .day),
                        y: .value("Step Count", $0.steps)
                    )
                }
            }
            
            GroupBox ( "Bar Chart - Step count") {
                Chart(currentWeek) {
                    BarMark(
                        x: .value("Week Day", $0.weekday, unit: .day),
                        y: .value("Step Count", $0.steps)
                    )
                }
            }
            
            GroupBox ( "Point Chart - Step count") {
                Chart(currentWeek) {
                    PointMark(
                        x: .value("Week Day", $0.weekday, unit: .day),
                        y: .value("Step Count", $0.steps)
                    )
                }
            }
            
            GroupBox ( "Rectangle Chart - Step count") {
                Chart(currentWeek) {
                    RectangleMark(
                        x: .value("Week Day", $0.weekday, unit: .day),
                        y: .value("Step Count", $0.steps)
                    )
                }
            }
            
            GroupBox ( "Area Chart - Step count") {
                Chart(currentWeek) {
                    AreaMark(
                        x: .value("Week Day", $0.weekday, unit: .day),
                        y: .value("Step Count", $0.steps)
                    )
                }
            }
        }
    }
}

使用 SwiftUI 图表创建的其他图表类型,显示每日步数

使用 SwiftUI 图表创建的其他图表类型,显示每日步数

让折线图增加可访问性

将图表植入 SwiftUI 的一个好处是,可以很容易地使用 可访问性修饰符 使图表变得可访问。为 StepCount 添加一个计算属性,将数据返回为一个字符串,可由 accessibilityLabel 使用。然后为图表中的每个标记添加可访问性标签和值。

struct StepCount: Identifiable {
    let id = UUID()
    let weekday: Date
    let steps: Int
    
    init(day: String, steps: Int) {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyyMMdd"
        
        self.weekday = formatter.date(from: day) ?? Date.distantPast
        self.steps = steps
    }
    
    var weekdayString: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyyMMdd"
        dateFormatter.dateStyle = .long
        dateFormatter.timeStyle = .none
        dateFormatter.locale = Locale(identifier: "en_US")
        return  dateFormatter.string(from: weekday)
    }
}
    GroupBox ( "Line Chart - Daily Step Count") {
        Chart(currentWeek) {
            LineMark(
                x: .value("Week Day", $0.weekday, unit: .day),
                y: .value("Step Count", $0.steps)
            )
            .accessibilityLabel($0.weekdayString)
            .accessibilityValue("\($0.steps) Steps")
        }
    }

在 SwiftUI 图表中使折线图可访问性

为折线图添加多个数据序列

折线图是比较两个不同系列数据的好方法。创建第二个系列,即前一周的步数,并将这两个系列添加到折线图中。

let previousWeek: [StepCount] = [
    StepCount(day: "20220710", steps: 15800),
    StepCount(day: "20220711", steps: 7300),
    StepCount(day: "20220712", steps: 8200),
    StepCount(day: "20220713", steps: 25600),
    StepCount(day: "20220714", steps: 16100),
    StepCount(day: "20220715", steps: 16500),
    StepCount(day: "20220716", steps: 3200)
]

let currentWeek: [StepCount] = [
    StepCount(day: "20220717", steps: 4200),
    StepCount(day: "20220718", steps: 15000),
    StepCount(day: "20220719", steps: 2800),
    StepCount(day: "20220720", steps: 10800),
    StepCount(day: "20220721", steps: 5300),
    StepCount(day: "20220722", steps: 10400),
    StepCount(day: "20220723", steps: 4000)
]

let stepData = [
    (period: "Current Week", data: currentWeek),
    (period: "Previous Week", data: previousWeek)
]

第一次尝试添加这两个系列的数据没有按预期显示。

struct LineChart2: View {
    var body: some View {
        GroupBox ( "Line Chart - Daily Step Count") {
            Chart {
                ForEach(stepData, id: \.period) {
                    ForEach($0.data) {
                        LineMark(
                            x: .value("Week Day", $0.weekday, unit: .day),
                            y: .value("Step Count", $0.steps)
                        )
                        .accessibilityLabel($0.weekdayString)
                        .accessibilityValue("\($0.steps) Steps")
                    }
                }
            }
        }
    }
}

第一次尝试在 SwiftUI Charts 中创建一个包含两个系列步数数据的折线图

第一次尝试在 SwiftUI Charts 中创建一个包含两个系列步数数据的折线图

显示步数系列

在折线图中显示多个基于工作日的步数系列

最初尝试在折线图中显示多组数据的问题是X轴使用了日期。当前的周数紧接着上一周,所以每一个点都是沿着X轴线性递增绘制的。

有必要只用工作日作为X轴的数值,这样所有的周日都在同一个X坐标上绘制。

StepCount中添加另一个计算属性,以便以字符串格式返回工作日的短日。

struct StepCount: Identifiable {

    . . .
    
        
    var shortDay: String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEE"
        return  dateFormatter.string(from: weekday)
    }
}

shortDay 用于图表中 LineMarks 的 x 值。另外,前景的样式设置为基于stepCount数组的周期。折线图使用 x 轴的工作日来显示两周的步数,以便在周之间进行比较。

struct LineChart3: View {
    var body: some View {
        VStack {
            GroupBox ( "Line Chart - Daily Step Count") {
                Chart {
                    ForEach(stepData, id: \.period) { steps in
                        ForEach(steps.data) {
                            LineMark(
                                x: .value("Week Day", $0.shortDay),
                                y: .value("Step Count", $0.steps)
                            )
                            .foregroundStyle(by: .value("Week", steps.period))
                            .accessibilityLabel($0.weekdayString)
                            .accessibilityValue("\($0.steps) Steps")
                        }
                    }
                }
                .frame(height:400)
            }
            .padding()

            Spacer()
        }
    }
}

SwiftUI图表中带有两个系列的步数数据的折线图

SwiftUI 图表中带有两个系列的步数数据的折线图

结论

在 SwiftUI Charts 中还有很多东西可以探索。使用这个框架显然比从头开始建立你自己的图表要好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/468521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Security环境搭建

Spring Security环境搭建 Spring BootSpring Security 认证&#xff1a;判断用户是否是用户合法用户的过程授权&#xff1a;判断系统用户可以访问或访问哪些权限资源 环境搭建 创建springBoot项目并导入springsecurity相关的依赖。 <dependencies><dependency>…

翻转课堂,让传统的以教为中心变成以学中心

翻转教室的故事起源于2007年&#xff0c;美国科罗拉多州洛矶山林地公园高中 (Woodland Park High School)的化学老师Jon Bergmann 和Aaron Sams&#xff0c;为了解决同学的缺课&#xff0c;先将预录好的课程上传到YouTube网站&#xff0c;让学生自行上网浏览学习。 他们发现学…

YOLO物体检测系列1.经典方法概述及评价指标体现

1. 深度学习经典检测方法&#xff1a; two-stage(两阶段)&#xff1a; Faster-rcnn Mask-RCNN系列 one-stage(单阶段)&#xff1a;Yolo系列 两阶段&#xff1a;一阶段实现RPN候选区域预选 二阶段基于候选区域再进行检测回归分类任务 单阶段&#xff1a;一个CNN卷积网络实现检测…

Ficus: 一款 markdown 编辑管理软件

Ficus Ficus 是一款 markdown 文档的编辑管理软件&#xff0c;由 ggG 团队开发。 Ficus 释义为“榕树”&#xff0c;榕树具有“冠盖如伞、一木成林“的特点。这也恰是本款软件想要为用户提供的核心服务&#xff1a;让用户的 md 文档可以像一棵榕树一样被浏览和编辑&#xff0…

EasyExcel动态头导出

前言 这段时间的项目中需要导出动态表格。 根据所选的参数导出对应的字段内容 下图所示选择下面几个tab页就需要导出对应的表头字段 下面为具体实现的效果。表头样式可以通过EasyExcel 提供的方法自定义。 具体实现 主要是通过 传入 exportItem 这个条件来决定导出的事项…

GCM与CCM的的规格和加解密过程

CCM CCM&#xff08;Counter with CBC-MAC&#xff09;是一种基于对称加密算法的认证加密&#xff08;Authenticated Encryption&#xff09;模式&#xff0c;结合了CBC-MAC&#xff08;Cipher Block Chaining Message Authentication Code&#xff09;用于消息认证和CTR&…

沃通TSA可信时间戳服务,保障电子数据法律效力

在全球信息化的大趋势下&#xff0c;以计算机及其网络为依托的电子数据&#xff0c;在证明案件事实的过程中起着越来越重要的作用&#xff0c;而可信时间戳已成为确立电子数据法律效力的重要技术之一。沃通TSA可信时间戳服务&#xff0c;提供具有法律效力的第三方可信时间戳认证…

android10 关闭默认输入法的“更正建议”

1. 场景 使用系统默认的输入法&#xff0c;在进行输入时&#xff0c;在输入法上方&#xff0c;会显示更正建议列表&#xff0c;同时会干扰我们的输入内容&#xff1a;会自动补全到输入框&#xff0c;而且删除不掉&#xff0c;甚至越删越多&#xff0c;非常讨厌。 如下&#x…

Spring IOC之对象的创建方式、策略及销毁时机和生命周期且获取方式

目录 一、对象的创建方式 1. 使用构造方法 2. 使用工厂类方法 3. 使用工厂类的静态方法 二、对象的创建策略 1. 单例策略 2. 多例策略 三、对象的销毁时机 四、生命周期方法 1. 定义生命周期方法 2. 配置生命周期方法 3. 测试 五、获取Bean对象的方式 1. 通过id/…

学习ZLmediaKit流媒体服务器时候遇到的问题

照zlmediakit的源码 自己复制了一份 然后有的地方编译不过修改了部分 测试的时候发现有两个问题 第一是 ffmpeg的ffplay 能播放 vlc不能播放 第二个问题是directProxy设置为0的时候 推流的时候 然后用ffplay播放 只有音频没有视频 查了好久终于解决这个问题 第一个…

pytest 自动化框架搭建-生成一个报告(alluer)

简单的case跑通了&#xff0c;尝试生成报告 1、使用allure-pytest 安装pip3 install allure-pytest 2、使用--alluredir../allure-results 如下我是直接在pytest.ini文件中使用命令 如下生成文件夹和json格式的文件 二、生成allure报告 1、安装allure 我是使用的命令直接…

字节超全学习流程图流出,100天涨薪10k,从功能测试到自动化测试...

今年年初&#xff0c;由于经济压力让我下定决心进阶自动化测试&#xff0c;已经24的我做了3年功能测试&#xff0c;坐标广州薪资定格在8k&#xff0c;可能是生活过的太安逸&#xff0c;觉得8000的工资也够了。 但是生活总是多变的&#xff0c;女朋友的突然怀孕&#xff0c;让我…

thinkphp6(tp6)初步小尝试(记录一下)

thinkphp6&#xff08;tp6&#xff09;初步小尝试&#xff08;记录一下&#xff09; 一、服务器环境二、创建tp6项目三、配置apache四、创建应用五、各应用入口六、简单模板 一、服务器环境 操作系统&#xff1a;ubuntu-22.04.2-live-server-amd64集成xampp(Apache MariaDB …

Python学习10:计算三维空间某点距离原点的欧式距离(python123)

题目描述: 欧几里得度量&#xff08;euclidean metric&#xff09;&#xff08;也称欧氏距离&#xff09;是一个通常采用的距离定义。三维空间里点a和b的坐标如果分别为a(x1,y1,z1)、b(x2,y2,z2)&#xff0c;则ab的距离的计算机公式是dist(a,b) √( (x1-x2)^2(y1-y2)^2(z1-z2…

史上最全Maven教程(四)

文章目录 &#x1f525;Maven聚合开发_聚合关系&#x1f525;Maven聚合开发_继承关系&#x1f525;Maven聚合案例_搭建父工程 &#x1f525;Maven聚合开发_聚合关系 之前我们在Idea中开发时会将项目的所有包放在同一个工程当中。 ⭐ domain&#xff1a;定义实体类 ⭐ dao&…

learn_C_deep_7 (switch 语句的基本理解、case 的作用、break的作用switch、case 推荐规则)

目录 switch 语句的基本理解 case语句的深度理解 case 的作用 case语句的要求 break 的作用 switch case 推荐规则 规则一&#xff1a; 规则二&#xff1a; 小结&#xff1a; switch 语句的基本理解 switch是一种控制语句&#xff0c;用于控制程序流程的走向。在 swit…

Zookeeper系统模型介绍

目录 一、数据模型 二、 节点的类型 &#xff08;1&#xff09;持久节点 &#xff08;2&#xff09;持久顺序节点 &#xff08;3&#xff09;临时节点 &#xff08;4&#xff09;临时顺序节点 三、客户端命令行 &#xff08;1&#xff09;创建节点 &#xff08;2&…

k8s- kubernetes证书过期替换之kubeadm命令 certs renew all方式

k8s- kubernetes证书过期替换之kubeadm命令 certs renew all方式 大纲 基础概念证书替换测试使用kubeadm alpha certs renew all 更新证书重启所有组件和kubelet.service生成kubelet-client-current.pem证书测试替换后集群是否正常工作 基础概念 本次测试使用的k8s集群使用…

【代码随想录】刷题Day9 --- 我有自信讲清楚KMP的next原理

字符串 --- 找子串匹配算法_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/130197908?spm1001.2014.3001.5501 首先具体KMP算法理论在上面的博客中&#xff0c;不过该博客我当初写的时候并没有了解next数组实现的过程是那样的&#xff0c;所以只…

【react全家桶学习】react中组件的props属性(详)

学过了vue的props属性&#xff0c;那react中的props属性如何使用呢&#xff1f; props的基本使用 我们先定义一个person组件 我们想要这三个参数动态传递进来&#xff0c;如何实现&#xff1f; 答&#xff1a;跟vue一样&#xff0c;直接在引用组件的地方进行传递即可。 在re…