iOS16使用SwiftUI Charts創建折線圖實現實例

前言

蘋果在 WWDC 2022 上推出瞭 SwiftUI 圖表,這使得在 SwiftUI 視圖中創建圖表變得異常簡單。圖表是以豐富的格式呈現可視化數據的一種很好的方式,而且易於理解。本文展示瞭如何用比以前從頭開始創建同樣的折線圖少得多的代碼輕松創建折線圖。此外,自定義圖表的外觀和感覺以及使圖表中的信息易於訪問也是非常容易的。

如以前的文章所示,不使用 SwiftUI Charts 也可以創建一個折線圖。然而,使用 Charts 框架可以提供大量的圖表來探索對應用程序中的數據最有效的方法,從而使它變得更加容易。

簡單折線圖

從包含一周的步數的數據開始,類似於 在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 有許多可用的圖表選項。這些可以通過將圖表標記從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 的一個好處是,可以很容易地使用 可訪問性修飾符 使圖表變得可訪問。為 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 中創建一個包含兩個系列步數數據的折線圖

顯示步數系列

在折線圖中顯示多個基於工作日的步數系列

最初嘗試在折線圖中顯示多組數據的問題是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 Charts 中還有很多東西可以探索。使用這個框架顯然比從頭開始建立你自己的圖表要好。

以上就是iOS16使用SwiftUI Charts創建折線圖實現實例的詳細內容,更多關於iOS16 SwiftUI Charts折線圖的資料請關註WalkonNet其它相關文章!

推薦閱讀: