SwiftUI 框架

利用 SwiftUI 的新 Charts API 輕鬆建立漂亮的折線圖

在 iOS 16 之前,我們需要構建自己的圖表、或是依靠第三方程式庫來建立圖表;在 iOS 16 的新版 SwiftUI 中,Apple 推出了 Charts 框架,讓我們可以更輕鬆地創建動畫化和互動的圖表。在這篇文章中,我會帶大家使用 Charts API,一步一步構建一個漂亮的折線圖!
利用 SwiftUI 的新 Charts API 輕鬆建立漂亮的折線圖
Photo by Isaac Smith on Unsplash
利用 SwiftUI 的新 Charts API 輕鬆建立漂亮的折線圖
Photo by Isaac Smith on Unsplash
In: SwiftUI 框架

在 iOS 16 的新版 SwiftUI 中,我最喜歡的其中一個功能就是 Charts 框架。在 iOS 16 之前,我們需要構建自己的圖表、或是依靠第三方程式庫來建立圖表。Apple 推出了這個新框架,開發者就可以更輕鬆地創建動畫化和互動的圖表。

我之前在這篇文章已經簡單介紹過 Charts API 的用法。在這篇文章中,讓我們來看看如何用 Charts API 來構建折線圖吧!

天氣數據

我們會示範使用 SwiftUI Charts API,來構建一個折線圖,顯示 2021 年 7 月至 2022 年 6 月香港、台北和倫敦的平均氣溫。

讓我們先建立一個 WeatherData 結構,來儲存天氣數據。

struct WeatherData: Identifiable {
    let id = UUID()
    let date: Date
    let temperature: Double

    init(year: Int, month: Int, day: Int, temperature: Double) {
        self.date = Calendar.current.date(from: .init(year: year, month: month, day: day)) ?? Date()
        self.temperature = temperature
    }
}

因為 Chart initializer 接受 Identifiable 物件的列表,所以我們要讓 WeatherData 遵從 Identifiable 協定。

我們要為每個城市創建一個陣列 (array),來儲存天氣數據。以下是倫敦的陣列:

let londonWeatherData = [ WeatherData(year: 2021, month: 7, day: 1, temperature: 19.0),
                          WeatherData(year: 2021, month: 8, day: 1, temperature: 17.0),
                          WeatherData(year: 2021, month: 9, day: 1, temperature: 17.0),
                          WeatherData(year: 2021, month: 10, day: 1, temperature: 13.0),
                          WeatherData(year: 2021, month: 11, day: 1, temperature: 8.0),
                          WeatherData(year: 2021, month: 12, day: 1, temperature: 8.0),
                          WeatherData(year: 2022, month: 1, day: 1, temperature: 5.0),
                          WeatherData(year: 2022, month: 2, day: 1, temperature: 8.0),
                          WeatherData(year: 2022, month: 3, day: 1, temperature: 9.0),
                          WeatherData(year: 2022, month: 4, day: 1, temperature: 11.0),
                          WeatherData(year: 2022, month: 5, day: 1, temperature: 15.0),
                          WeatherData(year: 2022, month: 6, day: 1, temperature: 18.0)
]

另外,我們也有一個陣列去儲存三個城市的天氣數據:

let chartData = [ (city: "Hong Kong", data: hkWeatherData),
                  (city: "London", data: londonWeatherData),
                  (city: "Taipei", data: taipeiWeatherData) ]

利用 Chart 和 LineMark 來建立一個簡單的折線圖

不論我們要利用 Charts 框架建立什麼圖表,都需要先匯入 Charts 框架:

import Charts

然後,我們就可以從 Chart 視圖開始。在 Chart 視圖內,讓我們提供一組 LineMark 來構建折線圖:

以上的程式碼繪製了一個折線圖,來顯示香港的平均氣溫。ForEach 語句 loop through 儲存在 hkWeatherData 中的所有項目。我們會為每個項目創建一個 LineMark 物件,當中 x 軸設置為日期,而 y 軸則設置為平均氣溫。

我們也可以選擇使用 frame 修飾符,來調整圖表的大小。如果我們在 Xcode 預覽中預覽程式碼,應該會看到以下折線圖:

swiftui-line-chart-simple

客製化圖表軸

我們可以利用 chartXAxischartYAxis 修飾符,來客製化 x 和 y 軸。比如說,如果我們想以數字格式顯示月份,我們可以將 chartXAxis 修飾符附加到 Chart 視圖:

.chartXAxis {
    AxisMarks(values: .stride(by: .month)) { value in
        AxisGridLine()
        AxisValueLabel(format: .dateTime.month(.defaultDigits))     
    }
}

chartXAxis 中,我們為月份的數值創建了一個 AxisMarks 的視覺標記 (visual mark)。針對每個數值,我們可以使用特定格式顯示一個 ValueLabel。以下這行程式碼就告訴了 SwiftUI 圖表,我們想要使用數字格式顯示月份:

.dateTime.month(.defaultDigits)

另外,我們也使用了 AxisGridLine 來添加一些 grid line。

至於 y 軸,我們之前是在後面(右側)顯示 y 軸的,我們想改為在前面(左側)顯示。讓我們如此附加 chartYAxis 修飾符:

做好改動之後,Xcode 預覽應該會把圖表更新如下。y 軸會在左側顯示,而月份的格式也會變成以數字格式顯示。另外,你也應該會看到 grid line。

swiftui-charts-changing-axis

客製化繪圖區域的背景顏色

我們可以利用 chartPlotStyle 修飾符,來更改繪圖區域的背景顏色。讓我們將修飾符附加到 Chart 視圖:

.chartPlotStyle { plotArea in
    plotArea
        .background(.blue.opacity(0.1))
}

然後,我們就可以使用 background 修飾符更改繪圖區域的顏色。在上面的例子中,我們把繪圖區域更改成淺藍色。

swiftui-line-chart-background

構建多於一條線的折線圖

現在,圖表只顯示單一數據(香港的天氣數據),那我們如何把倫敦和台北的天氣數據顯示在同一個折線圖中呢?

我們可以這樣重寫 Chart 視圖的程式碼:

Chart {
    ForEach(chartData, id: \.city) { series in
        ForEach(series.data) { item in
            LineMark(
                x: .value("Month", item.date),
                y: .value("Temp", item.temperature)
            )
        }
        .foregroundStyle(by: .value("City", series.city))
    }
}

‌我們有另一個 ForEach 來 loop through 三個城市的數據。我們在這裡使用了 foregroundStyle 修飾符,為每條線應用不同的顏色。我們不需要指定顏色,SwiftUI 會自動選擇顏色。

swiftui-multi-line-chart

現在,三個城市的符號都相同。如果要使用不同的符號,讓我們在 foregroundStyle 之後添加這行程式碼:

.symbol(by: .value("City", series.city))

如此一來,不同城市就會有不同的符號了。

swiftui-line-chart-symbol

客製化內插 (Interpolation) 方法

我們可以把 interpolationMethod 修飾符附加到 LineMark,來更改折線圖的內插方法。

.interpolationMethod(.stepStart)

如果我們把內插方法設置為 .stepStart,折線圖就會變成這樣:

swiftui-chart-interpolation-method

除了 .stepStart 之外,我們還可以使用以下設定:

  • cardinal
  • catmullRom
  • linear
  • monotone
  • stepCenter
  • stepEnd

總結

Charts 框架是 SwiftUI 一個很好的新功能,即使是 SwiftUI 的初學者,用幾行程式碼,就可以構建出漂亮的圖表。雖然這篇教學文章以折線圖為例子,但其實我們可以利用 Charts API 輕鬆地將折線圖轉換為其他圖表,例如長條圖。你可以參閱 Swift Charts 文檔深入了解這個 API。

備註:我們正就著 iOS 16 更新《精通 SwiftUI》一書。如你有意學習 SwiftUI,歡迎透過網頁購買書籍,我們會在今年免費為大家更新本書。

譯者簡介:Kelly Chan-AppCoda 編輯小姐。
作者
Simon Ng
軟體工程師,AppCoda 創辦人。著有《iOS 17 App 程式設計實戰心法》、《iOS 17 App程式設計進階攻略》以及《精通SwiftUI》。曾任職於HSBC, FedEx等跨國企業,專責軟體開發、系統設計。2012年創立AppCoda技術部落格,定期發表iOS程式教學文章。現時專注發展AppCoda業務,致力於iOS程式教學、產品設計及開發。你可以到推特與我聯絡。
評論
更多來自 AppCoda 中文版
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。