SwiftUI Charts 入门:从零到一,笑谈“柱”状人生(三)

概述

从 iOS 16 开始,Apple 为小伙伴们带来了全新的 SwiftUI Charts 框架,让我们可以用极少的代码便捷地绘制折线图、柱状图、饼图以及各种图,可谓"画龙点睛,一步登天"。

本系列文章将带宝子们从无到有,逐步拆解示例 TodayInYearsSetbacksComparisonChart 的源代码,并着重揭示几个开发中的"鬼斧神工"与"隐藏套路"。

在本篇博文中,您将学到如下内容:

    1. 动态刻度:按最大值自定义 Y 轴刻度
    • 3.1 为什么要自定义轴刻度?
    • 3.2 实现思路
    1. 最小值高光:Annotation + "大拇指"吸睛
    • 4.1 为什么要最小值?
    • 4.2 实现代码

想用 Charts 为自己精妙绝伦的 App 如虎添翼吗?看这篇就对啦! 无需等待,让我们马上开始 Charts 大冒险吧! Let's go!!!;)


3. 动态刻度:按最大值自定义 Y 轴刻度

3.1 为什么要自定义轴刻度?

默认坐标轴刻度依赖系统自动分配,有时会显得"参差不齐、无所适从",比如,若最大值是 7,系统可能给 10、5、0,显得不够精准。

3.2 实现思路

我们可以首先计算所有年份中挫折的最大值,然后根据它来更好的向用户呈现 y 轴刻度值的范围。

  1. 计算最大值let maxSbCount = sbCountInYears.values.max()!
  2. Stride 动态 :将刻度间隔设为 Double(maxSbCount / 2),并在 AxisMarks 中使用。

代码如下所示:

swift 复制代码
let sortedYears = sbCountInYears.keys.sorted(using: SortDescriptor(\.self, order: .reverse))
let maxSbCount = sbCountInYears.values.max { $0 < $1 }!

Chart {...}
.chartXAxis(.hidden)
.chartYAxis {
    //AxisMarks { value in
    // 使用挫折数量最大值来"精细化" y 轴的标签刻度
    AxisMarks(values: .stride(by: Double(maxSbCount / 2))) { value in
        if let y = value.as(Int.self), y >= 0 {
            AxisValueLabel("\(y)")
            AxisGridLine()
        }
    }
}
  • .stride(by:):每隔 maxSbCount / 2 绘制一条刻度;
  • value.as(Int.self):将坐标值转换为 Int 型的年份索引,避免自己转换带来的问题。

这样一来,我们就可以"量体裁衣、因时制宜" ------ 无论数据如何千变万化,刻度总能完美契合最大值,图表一看便知上下限,就问宝子们赞不赞呢?

4. 最小值高光:Annotation + "大拇指"吸睛

4.1 为什么要最小值?

除了最大值以外,对于挫折的最小值往往也值得小伙伴们"千锤百炼、别具匠心"的标注出来。

我们希望在挫折最小值对应的那个方柱上应用特殊效果(比如一个点赞的大拇指),来让用户投以钦佩的目光。

4.2 实现代码

swift 复制代码
let sortedYears = sbCountInYears.keys.sorted(using: SortDescriptor(\.self, order: .reverse))
let maxSbCount = sbCountInYears.values.max { $0 < $1 }!
let minSbCount = sbCountInYears.values.min { $0 < $1 }!

Chart {
    ForEach(sortedYears.indices, id: \.self) { yearIndex in
        
        let year = sortedYears[yearIndex]
        let sbCount = sbCountInYears[year]!
        let isThisYear = TimeMachine.shared.now.isSameYear(year)
        let isMinCount = minSbCount == sbCount
        
        BarMark(x: .value("年份序号", yearIndex), y: .value("次数", sbCount))
            .foregroundStyle(isThisYear ? .blue : .red)
            .annotation(position: .bottom, alignment: .center, spacing: 10) {
                Text(verbatim: "\(year)")
                    .foregroundStyle(.gray)
                    .font(.footnote)
                    .rotationEffect(.degrees(45))
                    .offset(x: 15)
            }
            .annotation(position: .top, spacing: 10) {
                Text(verbatim: "\(sbCount)")
                    .foregroundStyle(.red)
                    .font(.footnote.bold())
            }
            .annotation(position: .top, spacing: 30) {
                if isMinCount {
                    Image(systemName: "hand.thumbsup.fill")
                        .bold()
                        .foregroundStyle(.green.gradient)
                }
            }
    }
}
.chartXAxis(.hidden)
.chartYAxis {
    AxisMarks(values: .stride(by: Double(maxSbCount / 2))) { value in
        if let y = value.as(Int.self), y >= 0 {
            AxisValueLabel("\(y)")
            AxisGridLine()
        }
    }
}
  • 判断最小值if sbCount == minSbCount
  • 用 SFSymbol:Thumbs-up "点赞"图标,配合渐变色,让最小值脱颖而出。

在上面的代码中,我们主要做了以下几件事:

  • 计算所有挫折最小值对应的年份;
  • 在该年份柱子顶部用大拇指点赞;
  • 在每个柱子顶部标识出当前年份的挫折数

准备就绪,我们可以在 Xcode 预览中看一下运行效果:

正所谓:"画龙点睛、一鸣惊人" ------ 让挑剔的用户们一眼就认出最精彩的年份,棒棒哒!💯

在下一篇博文中,我们会用动画等精彩内容来为整个图表系列文章画上一枚完美的句号,期待吧!

总结

在本篇博文中,我们讨论了如何在柱状图上应用元素的最大最小值,小伙伴们值得拥有。

感谢观赏,我们下一篇再见啦!8-)

相关推荐
报错小能手3 小时前
ios开发方向——swift并发进阶核心 Task、Actor、await 详解
开发语言·学习·ios·swift
用户79457223954131 天前
【AFNetworking】OC 时代网络请求事实标准,Alamofire 的前身
objective-c·swift
报错小能手1 天前
SwiftUI 框架 认识 SwiftUI 视图结构 + 布局
ui·ios·swift
东坡肘子1 天前
被 Vibe 摧毁的版权壁垒,与开发者的新护城河 -- 肘子的 Swift 周报 #131
人工智能·swiftui·swift
报错小能手2 天前
ios开发方向——swift错误处理:do/try/catch、Result、throws
开发语言·学习·ios·swift
小夏子_riotous2 天前
openstack的使用——5. Swift服务的基本使用
linux·运维·开发语言·分布式·云计算·openstack·swift
mCell2 天前
MacOS 下实现 AI 操控电脑(Computer Use)的思考
macos·agent·swift
用户79457223954132 天前
【DGCharts】iOS 图表渲染事实标准——8 种图表类型、高度可定制,3 行代码画出一条折线
swiftui·swift
chaoguo12343 天前
Any metadata 的内存布局
swift·metadata·value witness table
tangweiguo030519874 天前
SwiftUI布局完全指南:从入门到精通
ios·swift