原文連接 : Core Plot Tutorial: Getting Started
原文做者 : Attila Hegedüs
譯文出自 : 掘金翻譯計劃
譯者 : llp0574(web前端領域)
校對者: yifili09,cdpath
譯者注:轉載請保留此頭部。前端
注意 :本篇教程已被 Attila Hegedüs 更新,可適用於 iOS 9 和 Swift 2.2。原始教程出自教程組成員 Steve Baranski。git
若是你曾經想在本身的 app 中引入圖表或圖形,那麼你應該已經考慮過下面兩種選項:github
本身寫。 經過使用 Core Graphics 或者 Quartz 這樣的框架編寫所有的繪製代碼。然而,這顯然要花費大量的功夫。web
買一個! 購買一個像 ShinobiControls 這樣的商業型框架。這或許能夠節省你的時間,但就要花錢啦。swift
可是若是你不想花費時間和精力從零開始寫(代碼),也不想花那麼多錢,該怎麼辦呢?這時候第三個選項就派上用場了:使用開源庫 Core Plot!app
Core Plot 是一個2D繪製庫,適用於 iOS,Mac OS X 和 tvOS。它使用了像 Quartz 和 Core Animation 這樣的蘋果應用框架,同時有着全面的測試覆蓋,並且是遵守BSD這個比較寬鬆的許可證進行發佈的。框架
在這個教程中,你將學習到如何使用 Core Plot 來建立餅圖和柱狀圖,同時還會實現一些很酷的圖表交互!ide
開始以前,你須要安裝好 Xcode 7.3 ,同時對 Swift , Interface Builder 和 storyboards 有所瞭解。若是你對這些主題知之甚少,那麼你應該在繼續閱讀本教程以前先學習一下咱們其餘的一些教程。函數
本教程同時還使用了 CocoaPods 去安裝一些第三方的依賴庫。若是你歷來沒使用過 CocoaPods 的話,那你還應該閱讀一下咱們關於它的教程。學習
在本教程中,你將建立一個在必定時間間隔內顯示貨幣匯率(狀況)的 App。從這裏下載本教程的入門項目,把它解壓縮後打開 SwiftRates.xcworkspace 。
項目的關鍵類在 App 這個文件夾和它的子文件夾下,它們包括了:
DataStore.swift
這是一個從 Fixer.io 請求貨幣匯率數據的幫助類。
Rate.swift
這是一個模型,表示給定日期裏的貨幣匯率。
Currency.swift
這是一個表示貨幣類型的模型。支持的貨幣類型定義在 Resources/Currencies.plist 裏。
MenuViewController.swift
這是一個app啓動後展現的第一個視圖控制器。它讓用戶選擇一個貨幣做爲基準而後再選兩個對照。
HostViewController.swift
這是一個容器視圖控制器,基於它的分段選項選中狀態去控制展現 PieChartViewController
或者 BarGraphViewController
的內容。它還會去檢查從 DataStore
請求來的匯率數據,由於它們也將在這個視圖控制器裏展示。
PieChartViewController.swift
這個控制器將用餅圖的形式展現一個給定日期裏的匯率。固然你首先要實現它!
BarGraphViewController.swift
這個控制器將以柱狀圖的形式展現幾天的匯率。當你掌握繪製餅圖的方法後,這個圖簡直小菜一碟!(看到我作的事情了嗎?拜託,這真的有點意思!);]
構建並運行看看這個教程入門項目實際展現。
點選 Get Rates 導航去到 HostViewController
控制的視圖而後能夠切換分段選項。這個 app 確實尚未實現太多功能...;]
是時候用 Core Plot 開始真正的繪製了!
首先你須要安裝 Core Plot,最簡單的方式是經過 CocoaPods 安裝。
把下面這行代碼添加進你的 Podfile 文件, pod 'SwiftDate'
這行的後面:
pod 'CorePlot', '~> 2.1'
打開 Terminal (終端),cd
進入你的項目根目錄,而後運行 pod install
。
安裝完成後,構建項目。
沒報錯吧?很好,如今你能夠隨便使用 Core Plot 啦,感謝 CocoaPods。:]
若是你遇到了任何報錯,能夠嘗試經過 sudo gem install cocoapods
更新一下 CocoaPods 而後再次運行 pod install
。
打開 PieChartViewController.swift 並添加下面這行引入:
import CorePlot
接着,添加下面這個屬性:
@IBOutlet weak var hostView: CPTGraphHostingView!
CPTGraphHostingView
負責「託管」一個圖表或圖形。你能夠把它想象成一個「圖形容器」。
而後,把下面這個類擴展添加到文件結尾的花括號以後:
extension PieChartViewController: CPTPieChartDataSource, CPTPieChartDelegate { func numberOfRecordsForPlot(plot: CPTPlot) -> UInt { return 0 } func numberForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex idx: UInt) -> AnyObject? { return 0 } func dataLabelForPlot(plot: CPTPlot, recordIndex idx: UInt) -> CPTLayer? { return nil } func sliceFillForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> CPTFill? { return nil } func legendTitleForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> String? { return nil } }
你將經過 CPTPieChartDataSource
爲一個 Core Plot 圖表提供數據,同時你會經過 CPTPieChartDelegate
獲得用戶交互的全部事件。隨着教程遞進,你將填滿這些方法。
繼續往下,打開 Main.storyboard 而後選擇 PieChartViewController
窗口。
在這個視圖上拖出一個新的 UIView
,而後把它的類更改爲 CPTGraphHostingView
,並將它鏈接到 hostView
。
對這個視圖的每一個方向添加約束讓撐滿父視圖,並確認沒有設置外邊距的約束:
設置一個你喜歡的背景色。我使用了透明度爲92%的灰度顏色。
如今回到 PieChartViewController.swift ,在 viewDidLoad()
後面添加下面的方法:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() initPlot() } func initPlot() { configureHostView() configureGraph() configureChart() configureLegend() } func configureHostView() { } func configureGraph() { } func configureChart() { } func configureLegend() { }
這樣子就正好在子視圖渲染好後設置了繪製策略。這裏是你最先爲視圖設置框架大小的地方,接下來你將須要配置繪製策略。
initPlot()
裏的每一個方法都表明了一個設置繪製策略的階段。這樣子可讓代碼保持其可維護性。
把下面這行添加進 configureHostView()
:
hostView.allowPinchScaling = false
這行代碼將對餅圖禁用手勢捏合縮放,它決定了託管視圖對捏合手勢是否會有反應。
接下來你須要添加一個圖表到hostView
。添加下面的代碼到 configureGraph()
裏吧:
// 1 - Create and configure the graph let graph = CPTXYGraph(frame: hostView.bounds) hostView.hostedGraph = graph graph.paddingLeft = 0.0 graph.paddingTop = 0.0 graph.paddingRight = 0.0 graph.paddingBottom = 0.0 graph.axisSet = nil // 2 - Create text style let textStyle: CPTMutableTextStyle = CPTMutableTextStyle() textStyle.color = CPTColor.blackColor() textStyle.fontName = "HelveticaNeue-Bold" textStyle.fontSize = 16.0 textStyle.textAlignment = .Center // 3 - Set graph title and text style graph.title = "\(base.name) exchange rates\n\(rate.date)" graph.titleTextStyle = textStyle graph.titlePlotAreaFrameAnchor = CPTRectAnchor.Top
下面對每一個部分的代碼進行分解:
首先你建立了一個 CPTXYGraph
的實例並指定它做爲 hostView
的 hostedGraph
。這就將圖表和託管視圖聯繫起來了。
這個 `CPTGraph` 包括了你所看到的標準圖表或圖形的所有東西:邊,標題,繪製相關數據,軸和圖例。 默認狀況下,`CPTXYGraph` 每一個方向都有一個`20`的內邊距。從咱們這個項目來看這樣並很差,因此你能夠顯式地將每一個方向的內邊距設置爲`0`。
接下來就是經過建立和配置一個 CPTMutableTextStyle
實例來設置該圖標標題的文本樣式。
最後,就是給你剛剛建立的圖表實例設置標題和其樣式。一樣你還須要指定標題錨點爲該視圖的上邊界。
構建並運行app,你應該就能夠看到這個圖表的標題展現在屏幕上了:
標題看起來不錯,但你知道接下來什麼會更棒嗎?確確實實地看到餅圖!
將下面的代碼添加進 configureChart()
:
// 1 - Get a reference to the graph let graph = hostView.hostedGraph! // 2 - Create the chart let pieChart = CPTPieChart() pieChart.delegate = self pieChart.dataSource = self pieChart.pieRadius = (min(hostView.bounds.size.width, hostView.bounds.size.height) * 0.7) / 2 pieChart.identifier = graph.title pieChart.startAngle = CGFloat(M_PI_4) pieChart.sliceDirection = .Clockwise pieChart.labelOffset = -0.6 * pieChart.pieRadius // 3 - Configure border style let borderStyle = CPTMutableLineStyle() borderStyle.lineColor = CPTColor.whiteColor() borderStyle.lineWidth = 2.0 pieChart.borderLineStyle = borderStyle // 4 - Configure text style let textStyle = CPTMutableTextStyle() textStyle.color = CPTColor.whiteColor() textStyle.textAlignment = .Center pieChart.labelTextStyle = textStyle // 3 - Add chart to graph graph.addPlot(pieChart)
下面看看這段代碼作了什麼:
首先獲取了剛剛建立的圖表的引用。
而後實例化一個 CPTPieChart
,將它的代理和數據源設置成這個視圖控制器自己,並配置它的一些外觀屬性。
接着配置這個圖表的邊框樣式。
配置它的文本樣式。
最後,將這個餅圖添加進剛剛引用的圖表裏。
若是如今從新構建並運行 app,你將看不到任何變化...由於你還須要實現這個餅圖的代理和數據源。
首先,用下面這段替代瞭如今的 numberOfRecordsForPlot(_:)
方法:
func numberOfRecordsForPlot(plot: CPTPlot) -> UInt { return UInt(symbols.count) ?? 0 }
這個方法決定了有多少塊(部分)顯示在餅狀圖上,它將爲每個標記顯示一塊(部分)。
接下來,用下面這段替換掉 numberForPlot(_:field:recordIndex:)
:
func numberForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex idx: UInt) -> AnyObject? { let symbol = symbols[Int(idx)] let currencyRate = rate.rates[symbol.name]!.floatValue return 1.0 / currencyRate }
餅圖會使用這個方法獲得索引爲 recordIndex
的貨幣符號的「總」值。
你應該注意到這個值並 不是 一個百分比值。取而代之的是,這個方法計算出了相對基準貨幣的貨幣匯率:返回的這個 1.0 / currencyRate
的值是"一個單位的基準貨幣是多少價值的另外的對照貨幣"的匯率。
CPTPieChart
將查看計算每一個分塊的百分比值,這個值最終決定了這個分塊佔多大。
下面,用下面這行替代掉 dataLabelForPlot(_:recordIndex:)
:
func dataLabelForPlot(plot: CPTPlot, recordIndex idx: UInt) -> CPTLayer? { let value = rate.rates[symbols[Int(idx)].name]!.floatValue let layer = CPTTextLayer(text: String(format: "\(symbols[Int(idx)].name)\n%.2f", value)) layer.textStyle = plot.labelTextStyle return layer }
這個方法返回了餅圖分片的標籤。指望的返回類型 CPTLayer
和 CALayer
有點類似,可是 CPTLayer 更加抽象,在 Mac OS X 和 iOS 上都能用,還提供了額外的繪圖細節供 Core Plot 使用。
這裏,建立並返回一個 CPTLayer
的子類 CPTTextLayer
去展現文本。
最後,將下面這段代碼替換掉 sliceFillForPieChart(_:, recordIndex:)
去添加分片的顏色:
func sliceFillForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> CPTFill? { switch idx { case 0: return CPTFill(color: CPTColor(componentRed:0.92, green:0.28, blue:0.25, alpha:1.00)) case 1: return CPTFill(color: CPTColor(componentRed:0.06, green:0.80, blue:0.48, alpha:1.00)) case 2: return CPTFill(color: CPTColor(componentRed:0.22, green:0.33, blue:0.49, alpha:1.00)) default: return nil } }
構建並運行,你就將看到一個漂亮的餅圖了:
這個圖表看上去至關不錯,可是添加一個圖例應該會讓它更棒。接下來你將學習怎麼添加一個圖例到這個圖表裏。
首先,用下面這段替換掉 configureLegend()
:
func configureLegend() { // 1 - Get graph instance guard let graph = hostView.hostedGraph else { return } // 2 - Create legend let theLegend = CPTLegend(graph: graph) // 3 - Configure legend theLegend.numberOfColumns = 1 theLegend.fill = CPTFill(color: CPTColor.whiteColor()) let textStyle = CPTMutableTextStyle() textStyle.fontSize = 18 theLegend.textStyle = textStyle // 4 - Add legend to graph graph.legend = theLegend if view.bounds.width > view.bounds.height { graph.legendAnchor = .Right graph.legendDisplacement = CGPoint(x: -20, y: 0.0) } else { graph.legendAnchor = .BottomRight graph.legendDisplacement = CGPoint(x: -8.0, y: 8.0) } }
一樣你也須要爲每一個分片提供圖例的數據。
要提供數據,就用下面這段替換掉 legendTitleForPieChart(_:recordIndex:)
:
func legendTitleForPieChart(pieChart: CPTPieChart, recordIndex idx: UInt) -> String? { return symbols[Int(idx)].name }
構建並運行,你就會獲得一個「帶圖例的」圖表啦。
看樣子你已是繪製餅圖的專家啦,可是時候去搞一個柱狀圖了!
打開 BarGraphViewController
並添加下面這行:
import CorePlot
接着,再添加下面這行:
@IBOutlet var hostView: CPTGraphHostingView!
其實就和餅圖同樣,託管視圖將承載這個柱狀圖的展現。
下一步,添加下面這些屬性:
var plot1: CPTBarPlot! var plot2: CPTBarPlot! var plot3: CPTBarPlot!
這裏聲明瞭三個 CPTBarPlot
類型的屬性,它們就至關於展現在圖表中的每種貨幣。
注意到一樣也有三個 IBOutlet
標籤和三個 IBAction
方法已經被定義了,你均可以在 storyboard 上看到它們。
最後,把下面這個類擴展添加到文件末尾:
extension BarGraphViewController: CPTBarPlotDataSource, CPTBarPlotDelegate { func numberOfRecordsForPlot(plot: CPTPlot) -> UInt { return 0 } func numberForPlot(plot: CPTPlot, field fieldEnum: UInt, recordIndex idx: UInt) -> AnyObject? { return 0 } func barPlot(plot: CPTBarPlot, barWasSelectedAtRecordIndex idx: UInt, withEvent event: UIEvent) { } }
這和建立餅圖的過程太像了:經過 CPTBarPlotDataSource
爲柱狀圖提供數據,經過 CPTBarPlotDelegate
捕捉用戶交互事件。你只須要複製粘貼就行了。
就像剛剛建立餅圖時候同樣,再次須要經過界面生成器把託管視圖添加進去。
回到 Main.storyboard 並選擇 BarGraphViewController
窗口。
在視圖上拖拽出一個新的 UIView
,將它的類更改成 CPTGraphHostingView
並將其輸出鏈接到控制器裏的 hostView
。
經過 UtilitiesSize Inspector (那個 刻度尺 選項卡)將它的框架更新到下面那樣:
X = 0, Y = 53, Width = 600, Height = 547
添加它和全部相鄰元素的約束,確認沒有設置 外邊距約束 。
最後,設置一個你喜歡的背景顏色。我再次用了92%透明度的灰度顏色。
既然 UI 已經經過上面的學習所有弄好了,是時候去繪製一個柱狀圖了。
首先,回到 BarGraphViewController
,你須要一對常量屬性。把下面這段添加到其餘屬性以前:
let BarWidth = 0.25 let BarInitialX = 0.25
你還須要一個幫助函數去計算最高的率值。把下面這段添加到 updateLabels()
以後:
func highestRateValue() -> Double { var maxRate = DBL_MIN for rate in rates { maxRate = max(maxRate, rate.maxRate().doubleValue) } return maxRate }
接着,把下面的方法添加到 highestRateValue()
以後:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() initPlot() } func initPlot() { configureHostView() configureGraph() configureChart() configureAxes() } func configureHostView() { } func configureGraph() { } func configureChart() { } func configureAxes() { }
是否是看上去很眼熟?是的,這些和以前的結構徹底同樣。
下面這行添加到 configureHostView()
裏:
hostView.allowPinchScaling = false
由於你不須要捏合縮放,因此你應該再次把它禁用。
接着,把下面那麼多行代碼添加到 configureGraph()
裏:
// 1 - Create the graph let graph = CPTXYGraph(frame: hostView.bounds) graph.plotAreaFrame?.masksToBorder = false hostView.hostedGraph = graph // 2 - Configure the graph graph.applyTheme(CPTTheme(named: kCPTPlainWhiteTheme)) graph.fill = CPTFill(color: CPTColor.clearColor()) graph.paddingBottom = 30.0 graph.paddingLeft = 30.0 graph.paddingTop = 0.0 graph.paddingRight = 0.0 // 3 - Set up styles let titleStyle = CPTMutableTextStyle() titleStyle.color = CPTColor.blackColor() titleStyle.fontName = "HelveticaNeue-Bold" titleStyle.fontSize = 16.0 titleStyle.textAlignment = .Center graph.titleTextStyle = titleStyle let title = "\(base.name) exchange rates\n\(rates.first!.date) - \(rates.last!.date)" graph.title = title graph.titlePlotAreaFrameAnchor = .Top graph.titleDisplacement = CGPointMake(0.0, -16.0) // 4 - Set up plot space let xMin = 0.0 let xMax = Double(rates.count) let yMin = 0.0 let yMax = 1.4 * highestRateValue() guard let plotSpace = graph.defaultPlotSpace as? CPTXYPlotSpace else { return } plotSpace.xRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(xMin), lengthDecimal: CPTDecimalFromDouble(xMax - xMin)) plotSpace.yRange = CPTPlotRange(locationDecimal: CPTDecimalFromDouble(yMin), lengthDecimal: CPTDecimalFromDouble(yMax - yMin))
下面是這段代碼邏輯的拆解:
首先,實例化一個 CPTXYGraph
,實際上就是一個柱狀圖,並將它關聯到 hostView
。
而後聲明一個 簡約的白色 默認主題併爲了展現 XY 軸去設置左側和下方的內邊距。
接着設置文本樣式,圖表標題以及標題位置。
最後,配置 CPTXYPlotSpace
,它負責將設備的座標系映射到圖表的座標系。針對這個圖表,你正在繪製三個使用了相同座標系的匯率。然而,也有可能每一個條形圖的座標系都是 分離 的。你還要在座標系中假定一個最大最小值匯率範圍。在後面的教程中,你將學習到怎麼樣在不提早設定範圍的狀況下自動調節空間大小。
既然已經建立好圖表了,那是時候增長一些繪製方法進去了!把下面的代碼添加到 configureChart()
裏:
// 1 - Set up the three plots plot1 = CPTBarPlot() plot1.fill = CPTFill(color: CPTColor(componentRed:0.92, green:0.28, blue:0.25, alpha:1.00)) plot2 = CPTBarPlot() plot2.fill = CPTFill(color: CPTColor(componentRed:0.06, green:0.80, blue:0.48, alpha:1.00)) plot3 = CPTBarPlot() plot3.fill = CPTFill(color: CPTColor(componentRed:0.22, green:0.33, blue:0.49, alpha:1.00)) // 2 - Set up line style let barLineStyle = CPTMutableLineStyle() barLineStyle.lineColor = CPTColor.lightGrayColor() barLineStyle.lineWidth = 0.5 // 3 - Add plots to graph guard let graph = hostView.hostedGraph else { return } var barX = BarInitialX let plots = [plot1, plot2, plot3] for plot: CPTBarPlot in plots { plot.dataSource = self plot.delegate = self plot.barWidth = BarWidth plot.barOffset = barX plot.lineStyle = barLineStyle graph.addPlot(plot, toPlotSpace: graph.defaultPlotSpace) barX += BarWidth }
接着來看看上面的代碼幹了什麼:
實例化每一個條形圖並設置它們的填充色。
實例化一個表明每一個條形圖的外部邊框的 CPTMutableLineStyle
實例。
給每一個條形圖提供「共同配置」。該配置包括設置數據源和代理,寬度和每一個條形圖在座標系中的相對位置(左右)以及線條樣式,最後,添加這個座標系到圖表當中。
雖然還不能夠看到柱狀圖展現出來,但經過構建 app 能夠去驗證目前爲止是否全部代碼均可以正確編譯經過。
爲了確切看到柱狀圖展現數據出來,須要去實現提供圖表所需數據的代理方法。
用下面這行替換掉 numberOfRecordsForPlot(:_)
:
return UInt(rates.count ?? 0)
該方法返回了應該展現的記錄的總數。
下面這段替換掉 numberForPlot(_:field:recordIndex:)
:
if fieldEnum == UInt(CPTBarPlotField.BarTip.rawValue) { if plot == plot1 { return 1.0 } if plot == plot2 { return rates[Int(idx)].rates[symbols[0].name]!.floatValue } if plot == plot3 { return rates[Int(idx)].rates[symbols[1].name]!.floatValue } } return idx
CPTBarPlotField.BarTip
的值代表了柱狀圖的相對大小。在你須要取回數據的時候可使用保留屬性計算出匯率,recordIndex
對應了利息率的位置。
構建並運行,你應該能夠看到和下面這張圖同樣的狀況:
已經快完成了!但請注意尚未任何東西指明每一個座標軸是表明什麼意思。
要解決這個問題,把下面這段添加進 configureAxes()
:
// 1 - Configure styles let axisLineStyle = CPTMutableLineStyle() axisLineStyle.lineWidth = 2.0 axisLineStyle.lineColor = CPTColor.blackColor() // 2 - Get the graph's axis set guard let axisSet = hostView.hostedGraph?.axisSet as? CPTXYAxisSet else { return } // 3 - Configure the x-axis if let xAxis = axisSet.xAxis { xAxis.labelingPolicy = .None xAxis.majorIntervalLength = 1 xAxis.axisLineStyle = axisLineStyle var majorTickLocations = Set<nsnumber>() var axisLabels = Set<cptaxislabel>() for (idx, rate) in rates.enumerate() { majorTickLocations.insert(idx) let label = CPTAxisLabel(text: "\(rate.date)", textStyle: CPTTextStyle()) label.tickLocation = idx label.offset = 5.0 label.alignment = .Left axisLabels.insert(label) } xAxis.majorTickLocations = majorTickLocations xAxis.axisLabels = axisLabels } // 4 - Configure the y-axis if let yAxis = axisSet.yAxis { yAxis.labelingPolicy = .FixedInterval yAxis.labelOffset = -10.0 yAxis.minorTicksPerInterval = 3 yAxis.majorTickLength = 30 let majorTickLineStyle = CPTMutableLineStyle() majorTickLineStyle.lineColor = CPTColor.blackColor().colorWithAlphaComponent(0.1) yAxis.majorTickLineStyle = majorTickLineStyle yAxis.minorTickLength = 20 let minorTickLineStyle = CPTMutableLineStyle() minorTickLineStyle.lineColor = CPTColor.blackColor().colorWithAlphaComponent(0.05) yAxis.minorTickLineStyle = minorTickLineStyle yAxis.axisLineStyle = axisLineStyle }</cptaxislabel></nsnumber>
簡單地說,上面的代碼首先爲軸線和標題定義了樣式,而後,爲圖表添加座標軸的設置並配置好 x 軸和 y 軸的一些屬性。
構建並運行就能夠看到這些改動的結果了。
更棒了對吧?惟一的缺陷在於這個座標軸太簡單了,沒辦法從這兒獲得一個準確的匯率展現。
你能夠修復這個問題以便當用戶點按在一個單獨的柱狀圖時,這個 app 能夠展現這個圖表示的匯率。爲了實現它,須要增長一個新的屬性:
var priceAnnotation: CPTPlotSpaceAnnotation?
而後把下面的代碼添加到 barPlot(_:barWasSelectedAtRecordIndex:)
:
// 1 - Is the plot hidden? if plot.hidden == true { return } // 2 - Create style, if necessary let style = CPTMutableTextStyle() style.fontSize = 12.0 style.fontName = "HelveticaNeue-Bold" // 3 - Create annotation guard let price = numberForPlot(plot, field: UInt(CPTBarPlotField.BarTip.rawValue), recordIndex: idx) as? CGFloat else { return } priceAnnotation?.annotationHostLayer?.removeAnnotation(priceAnnotation) priceAnnotation = CPTPlotSpaceAnnotation(plotSpace: plot.plotSpace!, anchorPlotPoint: [0,0]) // 4 - Create number formatter let formatter = NSNumberFormatter() formatter.maximumFractionDigits = 2 // 5 - Create text layer for annotation let priceValue = formatter.stringFromNumber(price)! let textLayer = CPTTextLayer(text: priceValue, style: style) priceAnnotation!.contentLayer = textLayer // 6 - Get plot index var plotIndex: Int = 0 if plot == plot1 { plotIndex = 0 } else if plot == plot2 { plotIndex = 1 } else if plot == plot3 { plotIndex = 2 } // 7 - Get the anchor point for annotation let x = CGFloat(idx) + CGFloat(BarInitialX) + (CGFloat(plotIndex) * CGFloat(BarWidth)) let y = CGFloat(price) + 0.05 priceAnnotation!.anchorPlotPoint = [x, y] // 8 - Add the annotation guard let plotArea = plot.graph?.plotAreaFrame?.plotArea else { return } plotArea.addAnnotation(priceAnnotation)
這裏須要一些解釋:
不要給一個隱藏的柱狀圖展現註解,而當圖沒有設置隱藏屬性的時候,在把切換開關整合到圖表以後,你就將實現它了。
這裏還要爲你的註解建立一個文本樣式。
獲得指定柱狀圖的匯率,而後若是它不存在一個註解對象,就建立一個。
若是沒有數值格式化的方法還須要建立一個,由於在匯率展現的時候須要先格式化它。
建立一個使用這個格式化匯率的文本層,並將註解的內容層設置到這個新的文本層上。
獲取你將展現的註解須要放置的柱狀圖索引。
基於這個索引計算註解的位置,並給使用這個計算位置註解設置 anchorPlotPoint
的值。
最後,將註解添加到圖表上。
構建並運行。每次當你點按圖表中的一個柱體時,該柱體所表示的值就應該正好在其上方彈出來。
棒極了! :]
這個柱狀圖看起來很棒,但屏幕最上方的切換開關並無起什麼做用,是時候改動它們了。
首先,須要添加一個幫助方法,把下面這段添加到 switch3Changed(_:)
以後:
func hideAnnotation(graph: CPTGraph) { guard let plotArea = graph.plotAreaFrame?.plotArea, priceAnnotation = priceAnnotation else { return } plotArea.removeAnnotation(priceAnnotation) self.priceAnnotation = nil }
這段代碼首先簡單地移除了一個若是存在的註解。
下一步,你但願用戶經過切換開關展現一個給定的貨幣匯率柱狀圖。
要作到這個功能,用下面這段替換到 switch1Changed(_:)
,switch2Changed(_:)
和 switch3Changed(_:)
的實現。
@IBAction func switch1Changed(sender: UISwitch) { let on = sender.on if !on { hideAnnotation(plot1.graph!) } plot1.hidden = !on } @IBAction func switch2Changed(sender: UISwitch) { let on = sender.on if !on { hideAnnotation(plot2.graph!) } plot2.hidden = !on } @IBAction func switch3Changed(sender: UISwitch) { let on = sender.on if !on { hideAnnotation(plot3.graph!) } plot3.hidden = !on }
這個邏輯至關簡單。若是開關設置了關閉,相關的圖和其可見的註解就將被隱藏,而若是設置爲開啓,則圖就會被設置爲可見。
構建並運行。如今你能夠在圖表中隨意切換每一個柱狀圖的展現了。教程至此已經完成了很不錯的工做!
你能夠從這裏下載一個已完成的項目。
哇哦,至關有趣!這個教程重點介紹了 Core Plot 的強大功能並但願提示了你該怎麼在你本身的 apps 裏使用它。
固然還能夠參考 Core Plot 倉庫獲取更多的信息,包括文檔,例子和一些小貼士。
還有,若是你對這個教程有任何的問題或者評論,歡迎加入下面的論壇進行討論。
祝你有個快樂的繪圖過程!