Swift 程式語言

Swift 教學:如何使用iOS Charts API 製作漂亮的圖表

Swift 教學:如何使用iOS Charts API 製作漂亮的圖表
Swift 教學:如何使用iOS Charts API 製作漂亮的圖表
In: Swift 程式語言

在這個章節,我們來看要如何使用由 Daniel Cohen Gindi所開發的ios-charts library 。 ios-charts 是由 Philipp Jahoda所建立,是非常受歡迎Android的函式庫,MPAndroidChart 的iOS接口。 有了這個函式庫,你可以在App中,快速且容易地加入各種型態的圖表。只要幾行程式,你就擁有能夠運作且可互動的圖表,並且可以高度客製化。

ios-charts-api

函式庫的主要核心包括:

  • 8種不同的圖表型式
  • 兩個軸向的縮放(以觸控手勢、分別對軸做縮放,或者以pinch手勢做縮放)
  • 拖曳/平移(以觸控手勢)
  • 圖表結合(線圖、長條圖、離散圖、K綫圖、氣泡圖)
  • 雙(分開的)Y軸
  • 手指畫圖(以觸控手勢將值畫進圖表)
  • 將值特別標示(以客製化的跳出視圖來顯示)
  • 多個/分離的軸
  • 儲存圖表至照片膠卷 / 以PNG/JPEG來輸出
  • 預定義的顏色模板
  • 圖例(可自動產生、客製化)
  • 客製化軸(x軸以及y軸)
  • 動畫(在x與y軸建立動畫)
  • 界線(提供額外的資訊,例如最大值等等
  • 全客製化(上色、字體、圖例、顏色、背景、手勢、虛線等等。)

讓我們開始吧

首先先 下載開始專案在這篇教學我們會用到它。這是一個簡單的應用,稱作iOSChartsDemo。當你執行App,你會得到一個有兩個項目的表格: Bar Charts 與 Other Charts。O在這些項目按下,會得到空白的視圖。在這個專案,我已經建立兩個會用到的視圖控制器(view controller): BarChartViewController 與 ChartsViewController。

接下來我們會加入函式庫至我們的專案中。你可以使用CocoaPods 來安裝函式庫,不過在這邊我們手動操作即可。

下載 ios-charts 專案。這個zip檔包含了函式庫(在檔案夾裡面名稱為Charts),與一個範例專案(稱作ChartsDemo)。倘若你要學習更多有關函式庫的部分,這個範例專案是一個很棒的資源。

將下載檔案解壓縮,並且複製Charts 檔案夾,然後在你的專案 (iOSChartsDemo) 的根目錄貼上它。在Finder 打開這個Charts檔案夾,並拖曳 Charts.xcodeproj 至Xcode專案中。如下圖所示。

charts01

接下來,從你的專案導覽器(Project Navigator)選取你的專案,並確定 iOSChartsDemo target有選取。 在右邊的General 鍵,至Embedded Binary區塊,並 在這個區塊按下+ 並加入Charts框架。從清單選取Charts.framework 並點擊Add。

charts02

倘若你要在 Objective-C 專案使用函式庫,你可以閱讀 Usage instructions來進一步了解。

以Command-B 來編譯專案,或者至Product>Build。倘若你不先編譯這個專案,Xcode會出現錯誤「Cannot load underlying module for ‘Charts」的錯誤訊息至你的檔案中。

現在我們準備建立我們第一個圖表。

建立一個長條圖(Bar Chart)

打開 BarChartViewController.swift 檔並加入import 陳述。

import Charts

打開Storyboard檔。 我們需要加入可以顯示圖表的視圖。從文件大綱(Documents Outline)選取Bar Chart View Controller ,並在屬性檢閱器(Attributes Inspector),在Extend EdgesUnder Top Bars打勾取消。 我不要圖表自己延伸至導覽欄(navigation bar)下方。

charts03

接下來拖曳一個視圖(View)至Bar Chart View Controller 並將邊緣定位如下圖所示,這個視圖是在控制器中主視圖的子視圖。

charts04

視圖選取後,至識別檢閱器(Identity Inspector),並將類別設為BarChartView。然後使用助理編輯器(Assistant Editor),來加入視圖的outlet 至BarChartViewController 類別。將outlet命名為 barChartView,在 BarChartViewController 類別,你的程式如下。

@IBOutlet weak var barChartView: BarChartView!

執行專案並從表格中選取Bar Chart,你應該可以得到一個訊息為「No chart data available」的視圖。

charts05

倘若你想要在沒有取得資料來產生圖表時,幫這個空白狀態(Blank Slates)顯示些不同的內容,你可以客製化這個訊息。在 viewDidLoad() 加入以下這行在函數底部。

barChartView.noDataText = "You need to provide data for the chart."

執行這個專案,就會顯示客製化的訊息內容了。

charts06

你可以進一步加上一個描述如下。這可以用來解釋給使用者了解,為何圖表是空白的,以及要怎麼做才能取得圖表,舉例來說在一個健身App可以讓使用者知道在資料彙整前,他們必須先記錄跑步數。

barChartView.noDataTextDescription = "GIVE REASON"

加入以下的屬性到這個類別。我們會使用它來儲存一些圖表的模擬數據。

var months: [String]!

加入以下的函數到這個類別。我們會用它來設定圖表。

func setChart(dataPoints: [String], values: [Double]) {
    barChartView.noDataText = "You need to provide data for the chart."
        
}

注意我曾經在前面 viewDidLoad() 這裏加入這個陳述。從 viewDidLoad()移除該陳述。我們會使用 setChart() 來客製化圖表。

viewDidLoad(),加入以下的程式至函數底部。

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0, 4.0, 18.0, 2.0, 4.0, 5.0, 4.0]
        
setChart(months, values: unitsSold)

我們設定一些虛擬數據,來給定一些產品一年中每個月的銷售單位。然後我們傳遞資料至 setChart()

要顯示圖表資料,我們必須建立一個 BarChartData 物件並設定它為 barChartView 的資料屬性。加入以下至setChart()底部。

var dataEntries: [BarChartDataEntry] = []
        
for i in 0..

以上的程式,我們建立一個 BarChartDataEntry物件的陣列。BarChartDataEntry初始器帶入每一個資料項目(data entry)的值、其值對應的項目索引,以及一個任意的標籤。

然後我們使用這個物件來建立一個 BarChartDataSet 物件,主要是建立來傳遞 BarChartDataEntry 物件的陣列,以及描述資料的標籤。

最後,我們使用這個來建立一個 BarChartData 物件,用來設定我們圖表視圖的資料。

執行這個App,你應該會得到有資料的長條圖了。

charts07

你可以在視圖的右側底部設定圖表的敘述。預設文字是設為「Description」如上圖所示。參考一下MPAndroidChart文件。這裏會告訴你如何能夠變更描述的位置,但是看一下iOS API,這個還沒有加入進去。這個函式庫還是需要維護,所以再過些時候會加進去。倘若你要變更描述的位置,你可以變更ChartViewBase 類別(也就是BarChartView 類別的子類別)的 drawDescription(context) 函數。

針對我們的App,我們會移除敘述文字。加入以下這行至 setChart() 的底部,來設定敘述文字為空字串。

barChartView.descriptionText = ""

客製化圖表

你可以透過一些屬性的變更來客製化圖表視圖的外觀,我們來介紹部分的效果,你可以查一下文件來找出哪些地方可以客製化。

首先我們變更長條圖的的預設顏色。加入以下這行至setChart()底部。

chartDataSet.colors = [UIColor(red: 230/255, green: 126/255, blue: 34/255, alpha: 1)]

以上設定跟我們資料組有關的顏色。我們以UIColor物件的陣列來設定。因為在我們的陣列中只有一種顏色,這可以讓所有的項目使用。

charts08

倘若你想對每一個資料項呈現不同的顏色,你需要提供更多你的資料項能用到的顏色,以我們的例子來說是12種顏色。倘若你的給的顏色少於全部資料項,那麼不同的顏色會從左到右分配給個別的資料柱,直到顏色用完之後再重頭開始(就像下圖所示,在模板中我們重複使用5種顏色來標示)

這個API也內建了一些預設的顏色模板,你可以使用它幫資料組設定不同的顏色。其中包括:

  • ChartColorTemplates.liberty()
  • ChartColorTemplates.joyful()
  • ChartColorTemplates.pastel()
  • ChartColorTemplates.colorful()
  • ChartColorTemplates.vordiplom()

如下所示,使用 ChartColorTemplates.colorful()

chartDataSet.colors = ChartColorTemplates.colorful()

charts09

使用下面這一行程式來變更x軸標籤的位置。

barChartView.xAxis.labelPosition = .Bottom

現在標籤在圖表下方了。

charts10

你也可以依下面方式變更圖表的背景顏色。

barChartView.backgroundColor = UIColor(red: 189/255, green: 195/255, blue: 199/255, alpha: 1)

加入以上程式的話,你會得到:

charts11

動畫

你可以加入一些動畫至圖表中,讓它更有趣些。有三種主要型態的動畫方法可以讓你同時對XY軸或個別對X週及Y軸來產生動畫。

  • animate(xAxisDuration: NSTimeInterval, yAxisDuration: NSTimeInterval)
  • animate(xAxisDuration: NSTimeInterval)
  • animate(yAxisDuration: NSTimeInterval)

你可以任意加入ChartEasingOption 至以上的函數。選項如下:

  • Linear
  • EaseInQuad
  • EaseOutQuad
  • EaseInOutQuad
  • EaseInCubic
  • EaseOutCubic
  • EaseInOutCubic
  • EaseInQuart
  • EaseOutQuart
  • EaseInOutQuart
  • EaseInQuint
  • EaseOutQuint
  • EaseInOutQuint
  • EaseInSine
  • EaseOutSine
  • EaseInOutSine
  • EaseInExpo
  • EaseOutExpo
  • EaseInOutExpo
  • EaseInCirc
  • EaseOutCirc
  • EaseInOutCirc
  • EaseInElastic
  • EaseOutElastic
  • EaseInOutElastic
  • EaseInBack
  • EaseOutBack
  • EaseInOutBack
  • EaseInBounce
  • EaseOutBounce
  • EaseInOutBounce

將以下這行加入 setChart()

barChartView.animate(xAxisDuration: 2.0, yAxisDuration: 2.0)

執行App,你會看到圖表以動畫方式加入視圖。我們對於兩個軸都設定2秒的動畫。

charts01

變更以上的狀態為:

barChartView.animate(xAxisDuration: 2.0, yAxisDuration: 2.0, easingOption: .EaseInBounce)

你會見到上面這行的特效如下。

charts02

界線

這個界線(limit line)是針對所有線圖、長條圖與散布圖(ScatterChart)的額外功能。。它可以在圖表特定軸(x或y軸)上另外顯示一條線。這樣的線是用來設定資料的目標值,協助使用者容易地了解是否有達到目標。

加入以下的程式至 setData(),來加入界線至圖表中。

let ll = ChartLimitLine(limit: 10.0, label: "Target")
barChartView.rightAxis.addLimitLine(ll)

現在執行這個App,你會見到一條紅線標註在單位10左右。上面的程式我們加入一個標籤到界線上,但是ChartLimitLine有另一個初始器沒有加上標籤,如果你不想加的話,可以省略。

charts12

觸控事件

倘若你執行這個App,你會注意到預設是以兩指以及按兩下來做縮放。還有,在某個柱狀條按下,可以突顯柱狀條已經在被按下的狀態。很棒的是我們不需要寫任何程式就可以取得這個功能,但是你可能想要加入更多的功能,例如在使用者按下柱狀條時有一些其他的功能。

想要對圖表內部的選取狀態做偵測,我們會使用 ChartViewDelegate 協定。

修改這個類別的宣告如下。

class BarChartViewController: UIViewController, ChartViewDelegate {

Add the following to viewDidLoad() after the call to super.viewDidLoad()

barChartView.delegate = self

加入以下的函數到類別中。

func chartValueSelected(chartView: ChartViewBase, entry: ChartDataEntry, dataSetIndex: Int, highlight: ChartHighlight) {
    println("\(entry.value) in \(months[entry.xIndex])")
}

以上這個函數在圖表視圖內的值被選取後會被呼叫,這裏我們印出被選擇月份的值。

圖表儲存

你可以將目前圖表的狀態存成圖片。你可以選擇將它存到照片膠卷中,或者你也可以設定要儲存的路徑。

首先,我們加入Save 按鈕至圖表視圖。打開Storyboard檔,至Bar Chart View Controller 拖曳一個導覽項目至視圖控制器的導覽欄(navigation bar),然後拖曳一個Bar Item並置於Navigation Item的右邊角落處。在屬性檢閱器移除Navigation Item 中Title屬性的「Title」文字並選取Bar Button Item並設定他的識別碼(Identifier)為Save,如下所示。

charts13

接下來,幫按鈕建立一個動作。稱作saveChart。在BarChartViewController類別中,你的程式應該如下所示。

@IBAction func saveChart(sender: UIBarButtonItem) {
        
}

修改以上的方法如下。

@IBAction func saveChart(sender: UIBarButtonItem) {
    barChartView.saveToCameraRoll()
}

執行這個App,當你按下Save按鈕,一個圖表的圖片便會儲存到照片膠卷。你可以使用Photos App來檢視。

你也可以採用以下的方法來設定儲存路徑。

barChartView.saveToPath(path: String, format: ChartViewBase.ImageFormat, compressionQuality: Double)

這個format 是表示格式可以是 .JPEG.PNGcompressionQuality 是表示壓縮品質,設為差異不大的格式(JPEG)。

更多圖表

這裏我們看一下其他幾個我們可以建立的圖表。我不做細節的說明,因為大部分都是已經看過了。

首先在Storyboard檔的Charts View Controller,在識別檢閱器(Identity Inspector)設定視圖的標籤為Pie Chart View視圖的Class為PieChartView。同樣針對Line Chart View 執行相同的步驟,將它的類別改為LineChartView。然後為這兩個視圖建立outlet,分別命名為pieChartViewlineChartView

然後修改 ChartsViewController 類別如下。

import UIKit
import Charts

class ChartsViewController: UIViewController {
    
    @IBOutlet weak var lineChartView: LineChartView!
    @IBOutlet weak var pieChartView: PieChartView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        
        let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
        let unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0]
        
        setChart(months, values: unitsSold)
        
    }
    
    func setChart(dataPoints: [String], values: [Double]) {
        
        var dataEntries: [ChartDataEntry] = []
        
        for i in 0..

在上面的程式,我們導入Charts 框架至類別,以及利用在建立長條圖一樣相同的方式來建立一個圓餅圖(pie chart),以及一個線圖(line chart),不過要注意的是,在我們使用父類別(super class)ChartDataEntry來建立資料項物件,而在長條圖範例,我們用的是BarChartDataEntry。不是所有的圖表都是ChartDataEntry的子類別,而這裡我們用到這個父類別。對於圖表資料組與圖表物件,我們針對特別的圖表使用特定的子類別。

倘若你執行App並從表格視圖選取 Other Charts ,你會見到一個線圖以及一個彩色的圓餅圖。你的App看起來可能會跟我們的以下這個圖不太一樣,因為我們使用隨機的數字來指定圓餅圖的顏色。

charts14

結論

我們見識到了使用ios-charts 函式庫所建立的幾個圖表型態。我們也接觸了在圖表上所能夠客製化的部分,倘若你想要了解這個函式庫的功能,你可以看一下你下載這個函式庫所內建的ChartsDemo 專案,另外你也可以看一下 project's Wiki。這個連結到Wiki頁面會導引至MPAndroidChart 專案文件。在撰寫這篇文章的時候,還沒有這個函式庫的iOS版本說明,但是因為API與Android有95%是相同的,這個Android文件對尋求一些幫助來說,還是很方便。

你可以在這裡下載完整的專案.

以下列出你可以建立的型態(圖片來自 原來的資料庫)

線圖(加上圖例,簡單的設計)

線圖(加上圖例,簡單的設計)

線圖(立方線)

線圖(單一資料組)

複合圖(長條圖與線圖)

長條圖(加上圖例、簡單設計)

長條圖(資料組群組)

水平長條圖

圓餅圖(加上選取...)

散佈圖(以方形、三角形、圓形等等的圖例)

K線圖(針對財經資料)

氣泡圖(由氣泡區域相覆蓋來表示值)

雷達圖(蜘蛛網圖)

譯者簡介:王豪勳 -渥合數位服務創辦人,畢業於台灣大學應用力學研究所,曾在半導體產業服務多年,近年來專注於協助客戶進行App軟體以及網站開發,平常致力於研究各式最軟硬體技術,擁有多本譯作。
原文How to Use iOS Charts API to Create Beautiful Charts in Swift
作者
Joyce Echessa
作為有經驗的網頁開發者同時從事手機程式開發的工作。閒時喜愛在網絡上發表教學文章,過程有樂趣也有挑戰,所謂教學相長,教與學的互動之中雙?
評論
更多來自 AppCoda 中文版
很好! 你已成功註冊。
歡迎回來! 你已成功登入。
你已成功訂閱 AppCoda 中文版 電子報。
你的連結已失效。
成功! 請檢查你的電子郵件以獲取用於登入的連結。
好! 你的付費資料已更新。
你的付費方式並未更新。