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

概述

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

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

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

    1. 倾斜的秘密:用 Annotation 自定义 X 轴标签
  • 2.1 自定义 x 轴标签
  • 2.2 拯救者:Annotation 出马!

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


2. 倾斜的秘密:用 Annotation 自定义 X 轴标签

2.1 自定义 x 轴标签

对于前一篇文章的问题,我们可以通过自己绘制图表的 x 轴标签来解决:

swift 复制代码
Chart {...}
.chartXAxis {
    AxisMarks { value in
        if let yearIdx = value.as(Int.self), yearIdx < sortedYears.count {
            let year = sortedYears[yearIdx]
            AxisValueLabel("\(year)")
            AxisGridLine()
        }
    }
}

在上面的代码中,我们使用图表的 chartXAxis 修改器"毅然决然"的抛弃了默认 x 轴标签,换成了自己 Nice 的年份显示:

不过,上面的结果没有显示所有的年份,这不是我们想要的。幸运的是,这可以通过 AxisMarks 中值的另一种构造器来"勉强"解决:

swift 复制代码
Chart {...}
.chartXAxis {
    AxisMarks(values: .stride(by: 1)) { value in
        if let yearIdx = value.as(Int.self), yearIdx < sortedYears.count {
            let year = sortedYears[yearIdx]
            AxisValueLabel("\(year)")
            AxisGridLine()
        }
    }
}

为什么说是"勉强"解决呢?因为即使这样,Charts 也总是忽略绘制最后一个年份(2017年):

所以,我们又该何去何从呢?

2.2 拯救者:Annotation 出马!

幸运的是,Charts 提供了一个 annotation 修改器方法,我们可以用它来进一步定制与图表元素相关的显示信息:

要达到用 annotation 模拟图表 x 轴标签的目的,我们需要解决两个小麻烦:

  1. 图片元素过分拥挤可能导致标签显示重叠
  2. 如何避免 annotation 下方多余的 y 轴标签?

为了让小伙伴们更清楚问题之所在,我们先用 annotation 实现一个初级版本一窥究竟:

swift 复制代码
Chart {
    ForEach(sortedYears.indices, id: \.self) { yearIndex in
        
        let year = sortedYears[yearIndex]
        let sbCount = sbCountInYears[year]!
        let isThisYear = TimeMachine.shared.now.isSameYear(year)
        
        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)
            }
    }
}
.chartXAxis(.hidden)

在上面的代码中,我们使用 annotation 完全替代了原本"不称职"的 x 轴标签,值得注意的是:我们需要使用 chartXAxis(.hidden) 修改器来隐藏默认的 x 轴标签。

运行结果如下所示:

看到我们之前所说的那两个麻烦了吗?

在这里,我们可以通过两种技术来解决它们,分别是标签倾斜定制 y 轴标签

swift 复制代码
Chart {
    ForEach(sortedYears.indices, id: \.self) { yearIndex in
        
        let year = sortedYears[yearIndex]
        let sbCount = sbCountInYears[year]!
        let isThisYear = TimeMachine.shared.now.isSameYear(year)
        
        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)
            }
    }
}
.chartXAxis(.hidden)
.chartYAxis {
    AxisMarks { value in
        if let y = value.as(Int.self), y >= 0 {
            AxisValueLabel("\(y)")
            AxisGridLine()
        }
    }
}

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

  1. 使用 rotationEffectoffset 修改器使 annotation 中的 Text 文本略微倾斜,让各个标签拉开空档;
  2. 使用自定义 y 轴标签忽略 0 以下标签;
  • .annotation(position: .bottom):在柱子底部添加自定义视图;
  • 倾斜 45° :用 .rotationEffect
  • .offset(x: 15):微调位置,防止与坐标轴重叠。

再次编译运行,现在效果是不是好多了呢?

如此"锦上添花、一举两得",既能显示完整年份,又不会压缩布局,何乐而不为呢?

在下一篇博文中,我们将继续劈风斩浪,让一个个图表布局上的"多事之秋"成为我们的"刀下冤魂",敬请期待吧!

总结

在本篇博文中,我们讨论了如何利用图表 Annotation 和定制标签绘制,来避免图表元素重叠和过滤不需要的轴标签。

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

相关推荐
报错小能手5 小时前
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