概覽
WWDC 2023 為我們帶來(lái)了 iOS 17,也為我們帶來(lái)了 SwiftUI 5.0。
在 SwiftUI 新版中,Apple 增加了很多重磅功能,也對(duì)原有功能做了大幅度升級(jí)。
對(duì)于 Charts 框架,? 新增了餅圖(Pie)類型并且加入了圖表元素的原生選擇功能。
在本篇博文中,就讓我們一起來(lái)看看 SwiftUI 5.0 中這些激動(dòng)人心的新功能吧!
Let’s go?。?!??
“大餅"與"甜甜圈”
SwiftUI 5.0 在 4.0 眾多圖表類型基礎(chǔ)之上,增加了全新的 餅圖(Pie) 類型,我們可以通過(guò)它來(lái)更形象的展示圖表數(shù)據(jù)。
注意:本文中的代碼需要 Xcode 15 beta 版才能編譯和運(yùn)行。
下面是 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)
想改為使用新餅圖類型非常簡(jiǎn)單,只需將上面的 BarMark 換為 SectorMark 即可:
SectorMark(angle: .value("power", item.power))
我們可以調(diào)整每塊“大餅”的空隙大?。╝ngularInset)和圓角的弧度(cornerRadius):
SectorMark(angle: .value("power", item.power),angularInset: 3.0)
.cornerRadius(10)
值得注意的是:Charts 中餅圖數(shù)據(jù)改變的動(dòng)畫效果做的也非常生動(dòng),SwiftUI 會(huì)自動(dòng)根據(jù)狀態(tài)的變化來(lái)合成自然的動(dòng)畫,無(wú)需多寫半行代碼。
不過(guò),“大餅”雖好,“甜甜圈”更佳!
小孩子才做選擇,光有“大餅”怎么行,我們連“甜甜圈”也統(tǒng)統(tǒng)都要了??!
實(shí)現(xiàn)“甜甜圈”(餅圖空心)效果也很容易,我們只需調(diào)整 SectorMark 構(gòu)造器中 innerRadius 屬性的值即可:
SectorMark(angle: .value("power", item.power),
innerRadius: .ratio(innerRadius),
angularInset: 3.0
)
好誘人的“甜甜圈”哦,有沒(méi)有想吃的欲望呢???
圖表元素的選中
除了加入新圖表類型以外,SwiftUI 5.0 中 Charts 終于可以支持原生選擇啦!
現(xiàn)在,我們無(wú)需再手動(dòng)計(jì)算是圖表中哪個(gè)元素被選中了,一切回歸簡(jiǎn)潔:
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:) 修改器方法將當(dāng)前選中的數(shù)據(jù)放入指定的綁定($rawSelectedDate)中。
除了選擇單個(gè)圖表元素,我們還可以選擇一段范圍內(nèi)的元素集合:
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)
那么問(wèn)題來(lái)了,能不能選中 SwiftUI 5.0 圖表新餅圖類型的“大餅”元素呢?答案是肯定的!
下面是官方視頻中對(duì)應(yīng)的代碼:
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)
類似的,? 通過(guò) chartAngleSelection(value:) 修改器方法實(shí)現(xiàn)了餅圖元素的選中:
不過(guò),單從這段代碼我們還是無(wú)法了解餅圖元素選中的實(shí)現(xiàn)細(xì)節(jié),比如:selectedAngle 是什么?它是如何轉(zhuǎn)換成 selectedName 的呢?
為什么 ? 在此要“猶抱琵琶半遮面”隱藏相關(guān)的細(xì)節(jié)呢?這不禁讓我預(yù)感到它會(huì)是一個(gè)“坑”!
“坑”中的實(shí)現(xiàn)很可能在 iOS 17 正式版中會(huì)有所不同,所以 ? 才會(huì)這樣“遮遮掩掩”。
想要了解更多相關(guān)的內(nèi)容,請(qǐng)移步如下鏈接觀賞:
- 有用的知識(shí)又增加了:為何無(wú)法編譯某些 ? WWDC 官方視頻中的代碼?
填上 WWDC 23 視頻中的“坑”
WWDC 23 中對(duì)應(yīng)內(nèi)容的官方視頻在下面,想要了解來(lái)龍去脈的小伙伴們可以“肆意”觀賞:
- Explore pie charts and interactivity in Swift Charts
盡管官方視頻中的代碼對(duì)如何完成餅圖元素選中功能“閃爍其詞”,但我們可以自己發(fā)揮“主觀能動(dòng)性”來(lái)大膽推測(cè)一下它的實(shí)現(xiàn)細(xì)節(jié):即自己搞定“甜甜圈”的選中功能。
首先我們要搞清楚的是, chartAngleSelection 方法參數(shù)中的綁定值到底是個(gè)啥:
public func chartAngleSelection<P>(_ binding: Binding<P?>) -> some View where P : Plottable
我們可以通過(guò)監(jiān)視 angleValue 的值,來(lái)看看它是如何跟隨我們點(diǎn)擊而變化的:
struct ContentView: View {
// 省略其它狀態(tài)定義...
@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) 方法中的綁定是一個(gè)數(shù)量值(定義成浮點(diǎn)數(shù)類型也可以),我們還發(fā)現(xiàn) angleValue 在 0° 位置附近點(diǎn)擊時(shí)值越小,而在 360° 位置點(diǎn)擊時(shí)值越大。
經(jīng)過(guò)驗(yàn)證可得:angleValue 最大值就是 items 中所有元素 power 值的和!據(jù)此,我們可以輕松寫一個(gè)從 angleValue 值找到對(duì)應(yīng)選中 item 的方法:
private func findSltItem() -> Item? {
guard let slt = angleValue else { return nil }
var sum = 0
// 若 angleValue 小于第一個(gè) item.power ,則表示選擇的是圖表中首張“大餅”!
var sltItem = items.first
for item in items {
sum += item.power
// 試探正確選中的餅圖元素
if sum >= slt {
sltItem = item
break
}
}
return sltItem
}
我們現(xiàn)在可以根據(jù)餅圖中當(dāng)前選中的 angleValue 值,輕松找到對(duì)應(yīng)的 Item 了:
struct ContentView: View {
// 省略其它狀態(tài)定義...
@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 {
// 點(diǎn)擊已被選中的元素時(shí)取消選擇
sltItem = nil
}else{
sltItem = item
}
}
}
}.padding(.vertical, 50)
ForEach(items) {...}
}
.navigationTitle("餅圖演示")
}
}
}
效果如下:
看來(lái)為 ? WWDC 官方代碼填坑的感覺(jué)也很不錯(cuò)哦????
總結(jié)
在本篇博文中,我們介紹了 WWDC 23 最新 SwiftUI 5.0(iOS 17)中關(guān)于圖表的新體驗(yàn),學(xué)習(xí)了如何創(chuàng)建餅圖(Pie)和實(shí)現(xiàn) Charts 元素的選中功能,小伙伴們還不趕快操練起來(lái)!文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-476995.html
感謝觀賞,再會(huì)!??文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-476995.html
到了這里,關(guān)于iOS 17(SwiftUI 5.0)帶來(lái)的圖表(Charts)新類型:“大餅”與“甜甜圈”的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!