iOS 17(SwiftUI 5.0)带来的图表(Charts)新类型:“大饼”与“甜甜圈”

news2024/11/25 18:58:08

在这里插入图片描述

概览

WWDC 2023 为我们带来了 iOS 17,也为我们带来了 SwiftUI 5.0。

在 SwiftUI 新版中,Apple 增加了很多重磅功能,也对原有功能做了大幅度升级。

对于 Charts 框架, 新增了饼图(Pie)类型并且加入了图表元素的原生选择功能。

在这里插入图片描述

在本篇博文中,就让我们一起来看看 SwiftUI 5.0 中这些激动人心的新功能吧!

Let’s go!!!😃


“大饼"与"甜甜圈”

SwiftUI 5.0 在 4.0 众多图表类型基础之上,增加了全新的 饼图(Pie) 类型,我们可以通过它来更形象的展示图表数据。


注意:本文中的代码需要 Xcode 15 beta 版才能编译和运行。


下面是 SwiftUI 4.0 Charts 条状图的展示:

在这里插入图片描述

代码如下:

@Model
final class Item {
    var name: String
    var power: Int
    var timestamp: Date
    
    init(name: String, power: Int) {
        self.name = name
        self.power = power
        timestamp = Date.now
    }
}

Chart(items) { item in
    BarMark(x: .value("power", item.power), stacking: .normalized)
        .foregroundStyle(by: .value("name", item.name))
}
.chartLegend(.hidden)

想改为使用新饼图类型非常简单,只需将上面的 BarMark 换为 SectorMark 即可:

SectorMark(angle: .value("power", item.power))

在这里插入图片描述

我们可以调整每块“大饼”的空隙大小(angularInset)和圆角的弧度(cornerRadius):

SectorMark(angle: .value("power", item.power),angularInset: 3.0)
    .cornerRadius(10)

在这里插入图片描述

值得注意的是:Charts 中饼图数据改变的动画效果做的也非常生动,SwiftUI 会自动根据状态的变化来合成自然的动画,无需多写半行代码。

不过,“大饼”虽好,“甜甜圈”更佳!

小孩子才做选择,光有“大饼”怎么行,我们连“甜甜圈”也统统都要了🍩!

实现“甜甜圈”(饼图空心)效果也很容易,我们只需调整 SectorMark 构造器中 innerRadius 属性的值即可:

SectorMark(angle: .value("power", item.power),
           innerRadius: .ratio(innerRadius),
           angularInset: 3.0
)

在这里插入图片描述

好诱人的“甜甜圈”哦,有没有想吃的欲望呢?😉

图表元素的选中

除了加入新图表类型以外,SwiftUI 5.0 中 Charts 终于可以支持原生选择啦!

现在,我们无需再手动计算是图表中哪个元素被选中了,一切回归简洁:

struct LocationDetailsChart: View {
  @Binding var rawSelectedDate: Date?

  var body: some View {
    Chart {
      ForEach(data) { series in
        ForEach(series.sales, id: \.day) { element in
          LineMark(
            x: .value("Day", element.day, unit: .day),
            y: .value("Sales", element.sales)
          )
        }
        .foregroundStyle(by: .value("City", series.city))
        .symbol(by: .value("City", series.city))
        .interpolationMethod(.catmullRom)
      }
    }
    .chartXSelection(value: $rawSelectedDate)
  }
}

如上代码所示,我们使用 chartXSelection(value:) 修改器方法将当前选中的数据放入指定的绑定($rawSelectedDate)中。

在这里插入图片描述

除了选择单个图表元素,我们还可以选择一段范围内的元素集合:

Chart(data) { series in
  ForEach(series.sales, id: \.day) { element in
    LineMark(
      x: .value("Day", element.day, unit: .day),
      y: .value("Sales", element.sales)
    )
  }
  ...
}
.chartXSelection(value: $rawSelectedDate)
.chartXSelection(range: $rawSelectedRange)

在这里插入图片描述

那么问题来了,能不能选中 SwiftUI 5.0 图表新饼图类型的“大饼”元素呢?答案是肯定的!

下面是官方视频中对应的代码:

Chart(data, id: \.name) { element in
  SectorMark(
    angle: .value("Sales", element.sales),
    innerRadius: .ratio(0.618),
    angularInset: 1.5
  )
  .cornerRadius(5)
  .foregroundStyle(by: .value("Name", element.name))
  .opacity(element.name == selectedName ? 1.0 : 0.3)
}
.chartAngleSelection(value: $selectedAngle)

类似的, 通过 chartAngleSelection(value:) 修改器方法实现了饼图元素的选中:

在这里插入图片描述

不过,单从这段代码我们还是无法了解饼图元素选中的实现细节,比如:selectedAngle 是什么?它是如何转换成 selectedName 的呢?

为什么  在此要“犹抱琵琶半遮面”隐藏相关的细节呢?这不禁让我预感到它会是一个“坑”!

“坑”中的实现很可能在 iOS 17 正式版中会有所不同,所以  才会这样“遮遮掩掩”。


想要了解更多相关的内容,请移步如下链接观赏:

  • 有用的知识又增加了:为何无法编译某些  WWDC 官方视频中的代码?

填上 WWDC 23 视频中的“坑”

WWDC 23 中对应内容的官方视频在下面,想要了解来龙去脉的小伙伴们可以“肆意”观赏:

  • Explore pie charts and interactivity in Swift Charts

尽管官方视频中的代码对如何完成饼图元素选中功能“闪烁其词”,但我们可以自己发挥“主观能动性”来大胆推测一下它的实现细节:即自己搞定“甜甜圈”的选中功能。

首先我们要搞清楚的是, chartAngleSelection 方法参数中的绑定值到底是个啥:

public func chartAngleSelection<P>(_ binding: Binding<P?>) -> some View where P : Plottable

我们可以通过监视 angleValue 的值,来看看它是如何跟随我们点击而变化的:

struct ContentView: View {
    // 省略其它状态定义...
    @Query private var items: [Item]
    @State private var angleValue: Int?
    
    var body: some View {
        NavigationView {
            List {
                Chart(items) { item in
                    SectorMark(angle: .value("power", item.power),
                               innerRadius: .ratio(innerRadius),
                               angularInset: 3.0
                    )
                    .cornerRadius(10)
                    .foregroundStyle(by: .value("name", item.name))
                }
                .chartLegend(.hidden)
                .chartAngleSelection($angleValue)
                .onChange(of: angleValue){ old,new in
                	// 探查 angleValue 的真正面目...
                    print("new angle value: \(new)")
                }.padding(.vertical, 50)
                
                ForEach(items) { ... }
            }
            .navigationTitle("饼图演示")
        }
    }
}

在这里插入图片描述

如上图所示:chartAngleSelection($angleValue) 方法中的绑定是一个数量值(定义成浮点数类型也可以),我们还发现 angleValue 在 0° 位置附近点击时值越小,而在 360° 位置点击时值越大。

经过验证可得:angleValue 最大值就是 items 中所有元素 power 值的和!据此,我们可以轻松写一个从 angleValue 值找到对应选中 item 的方法:

private func findSltItem() -> Item? {
    guard let slt = angleValue else { return nil }
    
    var sum = 0
    // 若 angleValue 小于第一个 item.power ,则表示选择的是图表中首张“大饼”!
    var sltItem = items.first
    for item in items {
        sum += item.power
        // 试探正确选中的饼图元素
        if sum >= slt {
            sltItem = item
            break
        }
    }
    return sltItem
}

我们现在可以根据饼图中当前选中的 angleValue 值,轻松找到对应的 Item 了:

struct ContentView: View {
    // 省略其它状态定义...
    @Query private var items: [Item]
    @State private var angleValue: Int?
    @State private var sltItem: Item?
    
    var body: some View {
        NavigationView {
            List {
                Chart(items) { item in
                    SectorMark(angle: .value("power", item.power),
                               innerRadius: .ratio(innerRadius),
                               angularInset: 3.0
                    )
                    .cornerRadius(10)
                    .foregroundStyle(by: .value("name", item.name))
                    .opacity(sltItem?.id == item.id ? 1.0 : 0.3)
                }
                .onChange(of: angleValue){ old,new in
                    withAnimation {
                        if let item = findSltItem() {
                            if item == sltItem {
                                // 点击已被选中的元素时取消选择
                                sltItem = nil
                            }else{
                                sltItem = item
                            }
                        }
                    }
                }.padding(.vertical, 50)
                
                ForEach(items) {...}
            }
            .navigationTitle("饼图演示")
        }
    }
}

效果如下:

在这里插入图片描述

看来为  WWDC 官方代码填坑的感觉也很不错哦😘💯

总结

在本篇博文中,我们介绍了 WWDC 23 最新 SwiftUI 5.0(iOS 17)中关于图表的新体验,学习了如何创建饼图(Pie)和实现 Charts 元素的选中功能,小伙伴们还不赶快操练起来!

感谢观赏,再会!😎

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

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

相关文章

容器镜像差异分析工具 container-diff

概述 container-diff 是google出的一个容器差异比较工具&#xff0c;通过这个工具可以比较两个镜像之间存在的文件差异、RPM包差异、apt包差异、pip包差异和node包差异。 container-diff 也包括了对单个镜像分析能力&#xff0c;像文件分析啊、apt包、rpm包分析等功能。 在日常…

Python爬虫——怎么搭建和维护一个本地IP池

目录 背景 一、什么是本地代理IP池 二、代理IP池功能架构图 三、各个组件功能说明及示例代码 1. IP池管理器 2. 代理IP获取器 3. IP质量检测器 4、数据存储器 5、API接口层 6、应用程序 总结 背景 在我们进行爬虫工作时&#xff0c;经常需要使用代理IP。大多数代理…

unity2d粒子特效

文章目录 前言先看效果一、2d平台雨1. 配置2. 图片素材3. 最终效果 二、脚步灰尘效果1. 配置2. 代码调用3. 效果 三、受伤血液四溅效果1. 配置2. 效果 待续四、工程源码五、参考六、完毕 前言 我只是我抽空写了一些简单的2d粒子特效&#xff0c;后面如果接触新的不错的2d特效&a…

Maven 安装

一. 下载 apache官网下载 Maven&#xff1a;Maven – Download Apache Maven &#xff0c;根据需要下载不同压缩包。 将压缩包进行解压&#xff0c;最好放在无中文目录下解压。 二. 安装 三. 配置 1. 配置maven本地仓库 打开解压后的文件夹&#xff0c;找到conf文件夹&#…

银行vr元宇宙全景虚拟展馆提供更加真实、立体、高效的数字资产交易场景

为了贯彻国家普惠金融政策&#xff0c;使金融如无惠及广大群体,宇宙技术在金融行业中的应用将进一步提升金融消费体验感觉和金融管理水平。打造元宇宙金融服务平台&#xff0c;构建虚实结构的金融服务世界&#xff0c;培育和管理好数字机器人员工队伍&#xff0c;提升金融业务各…

postman登录鉴权之接口测试

一.背景 在做接口测试的时候&#xff0c;有些接口向后台请求数据的时候&#xff0c;是需要用户在登录情况下才有数据返回。 以电商平台为例&#xff0c;用户的个人中心&#xff0c;用户的订单列表&#xff0c;用户的支付信息等等&#xff0c;所有用户维度的数据都是需要登录态…

Django - 页面静态化和crontab定时任务(二)

一. 前言 一个网页会有很多数据是不需要经常变动的&#xff0c;比如说首页&#xff0c;变动频率低而访问量大&#xff0c;我们可以把它静态化&#xff0c;这样就不需要每次有请求都要查询数据库再返回&#xff0c;可以减少服务器压力 我们可以使用Django的模板渲染功能完成页面…

app反编译查看是否被混淆或者混淆是否成功

同时打 debug包和release包&#xff0c;生成的目录在build->output文件夹下面 一般直接运行的apk 包是在build/intermediates/apk/debug 目录下 方法1&#xff1a;Android studio 安装插件jadx build成apk 后 直接选中 右键 在Jadx GUI中反编译 就可以查看代码 方法2&…

距离保护的影响因素

1、汲出电流和助增电流的影响 当保护安装处与故障点之间有分支电源时&#xff0c;如图所示&#xff0c;分支电源将向故障点K送短路电流ICB&#xff0c;使流过故障线路的电流IBKIAB ICB&#xff0c;大于实际流过保护1的电流IAB&#xff0c;所以ICB称作助增电流。 由于助增电流的…

第一章操作系统引论

目录 一、熟悉的操作系统 二、计算机系统的层次结构 三、操作系统的概念 四、操作系统的功能 4.1 系统资源的管理者 4.2 向上层提供方便易用的服务 4.2.1 GUI&#xff1a;图形化用户接口&#xff08;Graphical UserInterface&#xff09; 4.2.2 命令接口 4.2.3 程序接…

当杠精型AI丈夫遇上阴阳怪气AI老婆,你的代码玩得转吗?

玩趣味活动 赢千元奖金 DataFountain社区首个趣味活动来啦&#xff01;&#xff01;&#xff01; 活动已发车&#xff0c;来不及解释了&#xff0c;先上车&#xff1a;https://www.datafountain.cn/information/activity/3 人工智能问答爆火&#xff0c;你的算法技能储备跟上…

达梦数据库ODBC配置及达梦与mysql创建DBLINK测试

目录 官网ODBC配置... 3 1、ODBC下载官网... 3 2、上传安装包并解压... 3 3、安装odbc. 3 4、安装依赖... 4 5、再次执行安装即可... 4 6、查看版本及配置文件... 4 Mysql-ODBC配置... 5 一、达梦服务器... 5 1、下载odbc包... 5 2、安装... 6 3、报错... 6 4、先…

STM32——01-开发软件Keil5及STM32CubeMX的安装

1.1开发环境的安装 编程语言&#xff1a;C语言 需要安装的软件有两个&#xff1a;Keil5和STM32CubeMX 安装 安装包&#xff08;不需要太新&#xff0c;以 MDK324 为例&#xff0c;最新的 MDK327 有问题&#xff09; 安装过程一路下一步即可&#xff08;建议不要安装在 C …

Gitlab集成jira

实现功能 gitlab提交和合并分支&#xff0c;会自动将comment信息提交到JIRA上的相关问题的页面gitlab可以修改jira上问题的状态 集成说明 gitlab集成Jira 按项目集成&#xff0c;因此gitlab上的每个项目对应jira上的对应项目由项目管理员&#xff08;一般为接口人&#xff…

如何用Python开发QQ机器人

前言 虽然该文最终是达到以python开发mirai机器人的目的&#xff0c;但起步教程&#xff0c;尤其是环境配置上仍然有大量的相同操作&#xff0c;对其他编程语言仍有借鉴之处 假设你已经安装好了 Java、Python等运行必须的环境 mirai生态 mirai官方生态文档 要使用mirai开发…

【tableau】基础图形绘制

4.5 文字云 第一步&#xff1a; 想要突出显示的字段拖入 “标签”&#xff0c;如 客户名称 第二步&#xff1a; 展示大小的字段拖入“大小”&#xff0c;默认黑色 第三步&#xff1a;展示大小的字段拖入“颜色”&#xff0c;颜色不是喜欢的&#xff0c;可以右侧编辑颜色 4.6…

Vue中如何进行地图展示与交互(如百度地图、高德地图)?

Vue中如何进行地图展示与交互 随着移动互联网的普及&#xff0c;地图应用已经成为人们生活中不可或缺的一部分。在Vue.js中&#xff0c;我们可以使用第三方地图库&#xff08;如百度地图、高德地图&#xff09;来实现地图的展示和交互。本文将介绍如何在Vue.js中使用百度地图和…

IDEA整合GO并传module工程

IDEA整合Go 安装包环境配置idea配置并创建test mode 安装包 1.去官网下载对应还的安装包 官网下载地址 我选择下载的window 版本&#xff1a; 直接按照对应的目录&#xff0c;然后点击下一步 环境配置 1.配置go环境变量 在高级环境变量PAHT中添加安装包的**/bin 目录&…

主流自动化测试框架,这5种真的帮助巨大。

今天我们要向大家介绍的是常见5种主流自动化测试框架&#xff0c;包括优缺点等内容&#xff0c;供大家参考学习。 1.ATF 自动化测试框架AutoTestFramework是B/S架构框架&#xff0c;可实现Selenium等多种自动化测试全流程、团队化管理的高级框架平台&#xff0c;通过集成自动化…

想必大家都为测试用例头疼过,那么如何才能设计出一个“好的”测试用例

目录 前言&#xff1a; “好的”测试用例具备的特征 1&#xff0e;等价类划分方法 2&#xff0e;边界值分析方法 “好的”测试用例的设计方法 测试用例设计的其他经验 作为测试人员&#xff0c;需要注意以下几点&#xff1a; 前言&#xff1a; 设计一个“好的”测试用例&…