グラフを描画してみた(swift)

#はじめに
objective-cでつくったはいいけど**使っていない**クラスをswiftに書き換えてgithubにあげてみたので、そのクラスについて紹介したいと思います。自分はまだ使う場面がない（今のところ思いつかない）ので、あわよくばだれかに使ってもらえたらいいなと思います。(第四弾)

[第一弾（時計）](https://qiita.com/am10/items/0222e6966d58062d2eca)

[第二弾（スピードメーター）](https://qiita.com/am10/items/0fe8cffac7dd7659eb2a)

[第三弾（めくるカレンダー）](https://qiita.com/am10/items/2a929ca8196f33cb1d4a)

2019/04/21 せっかくなんでswift5.0対応しました
2019/10/16 せっかくなんでSwiftPM対応しました

#GitHub
今回はこちらのクラスについて紹介します。

[AMChart](https://github.com/adventam10/AMChart)

* AMLineChartView
* AMScatterChartView
* AMBarChartView
* AMRadarChartView
* AMPieChartView

#見た目

![chart.gif](https://qiita-image-store.s3.amazonaws.com/0/225999/1d3e072c-0148-3d8a-63c1-4a5eddeebaae.gif)

#機能
折れ線グラフ、散布図、棒グラフ、レーダーチャート、円グラフの表示ができる

#使い方
1. xibにカスタムクラスを設定  
<img width="254" alt="custom_class.png" src="https://qiita-image-store.s3.amazonaws.com/0/225999/4451b4a1-84fe-e5cb-7414-dd0543df2f7a.png">

2. 目盛りの最小値・最大値、目盛りの数などを設定  
<img width="253" alt="IBInspectable.png" src="https://qiita-image-store.s3.amazonaws.com/0/225999/205b2e97-52ae-2920-0ac9-458cc596a14e.png">

3. デリゲートを設定する  
デリゲートはtableViewを意識してつくりました。
	## AMLineChartView
	sectionが各グラフ、rowが各点に相当する
	
	```swift
	protocol AMLineChartViewDataSource: AnyObject {
    
    /// グラフの数を設定する
    func numberOfSections(in lineChartView: AMLineChartView) -> Int
    
    /// 折れ線の点の数を設定する
    func numberOfRows(in lineChartView: AMLineChartView) -> Int
    
    /// 折れ線の各点の値を設定する
    func lineChartView(_ lineChartView: AMLineChartView, valueForRowAtIndexPath indexPath: IndexPath) -> CGFloat
    
    /// 各グラフの色を設定する
    func lineChartView(_ lineChartView: AMLineChartView, colorForSection section: Int) -> UIColor
    
    /// X軸の文字を設定する
    func lineChartView(_ lineChartView: AMLineChartView, titleForXlabelInRow row: Int) -> String
    
    /// 各グラフの点の形を設定する
    func lineChartView(_ lineChartView: AMLineChartView, pointTypeForSection section: Int) -> AMPointType
}
	```
	
    点の形には下記の種類がある
    
    ```swift
    enum AMPointType {
    /// 丸（塗りつぶしなし）
    case type1
    /// 丸（塗りつぶしあり）
    case type2
    /// 四角（塗りつぶしなし）
    case type3
    /// 四角（塗りつぶしあり）
    case type4
    /// 三角（塗りつぶしなし）
    case type5
    /// 三角（塗りつぶしあり）
    case type6
    /// ひし形（塗りつぶしなし）
    case type7
    /// ひし形（塗りつぶしあり）
    case type8
    /// ×印
    case type9
}
    ```
	こんな感じ
	<img width="500" alt="chart_l.png" src="https://user-images.githubusercontent.com/34936885/67146924-14a2b080-f2cb-11e9-9720-4290ac1b9832.png">
　
	## AMScatterChartView
	
	sectionが各グラフ、rowが各点に相当する
	
	```swift
	protocol AMScatterChartViewDataSource: AnyObject {
    
    /// グラフの数を設定する
    func numberOfSections(in scatterChartView: AMScatterChartView) -> Int

    /// 各グラフの点の数を設定する
    func scatterChartView(_ scatterChartView: AMScatterChartView, numberOfRowsInSection section: Int) -> Int
    
    /// 散布図の各点の値を設定する
    func scatterChartView(_ scatterChartView: AMScatterChartView, valueForRowAtIndexPath indexPath: IndexPath) -> AMScatterValue
    
    /// 各グラフの色を設定する
    func scatterChartView(_ scatterChartView: AMScatterChartView, colorForSection section: Int) -> UIColor

    /// 各グラフの点の形を設定する
    func scatterChartView(_ scatterChartView: AMScatterChartView, pointTypeForSection section: Int) -> AMPointType
}
	```
	
    グラフの値は下記の構造体を設定する
    
    ```swift
    struct AMScatterValue {
    
    	var xValue : CGFloat = 0
    	var yValue : CGFloat = 0
    
    	init(x :CGFloat, y :CGFloat) {
        	xValue = x
        	yValue = y
    	}
	}
	```
	
	点の種類は折れ線グラフと同様
	こんな感じ
	<img width="500" alt="chart_s.png" src="https://user-images.githubusercontent.com/34936885/67146918-fccb2c80-f2ca-11e9-8348-ee00d5febf12.png">

	## AMBarChartView
	
	sectionが各グラフ、rowが各項目に相当する
	
	```swift
	protocol AMBarChartViewDataSource: AnyObject {
    
    /// グラフの数を設定する（棒の数）
    func numberOfSections(in barChartView: AMBarChartView) -> Int
    
    /// 各グラフの項目数を設定する
    func barChartView(_ barChartView: AMBarChartView, numberOfRowsInSection section: Int) -> Int
    
    /// 各グラフの項目の値を設定する
    func barChartView(_ barChartView: AMBarChartView, valueForRowAtIndexPath indexPath: IndexPath) -> CGFloat
    
    /// 各グラフの項目の色を設定する
    func barChartView(_ barChartView: AMBarChartView, colorForRowAtIndexPath indexPath: IndexPath) -> UIColor
    
    /// x軸の文字を設置する
    func barChartView(_ barChartView: AMBarChartView, titleForXlabelInSection section: Int) -> String
}
	```
	こんな感じ
	<img width="500" alt="chart_b.png" src="https://user-images.githubusercontent.com/34936885/67146915-f63cb500-f2ca-11e9-9073-5eb8f3314360.png">

	## AMRadarChartView
	
	sectionが各グラフ、rowが各項目に相当する
	
	```swift
	protocol AMRadarChartViewDataSource: AnyObject {
    
    /// グラフの数を設定する
    func numberOfSections(in radarChartView: AMRadarChartView) -> Int
    
    /// 項目数を設定する（頂点の数）
    func numberOfRows(in radarChartView: AMRadarChartView) -> Int
    
    /// 各項目の値を設定する
    func radarChartView(_ radarChartView: AMRadarChartView, valueForRowAtIndexPath indexPath: IndexPath) -> CGFloat
    
    /// 各グラフの塗りつぶし色を設定する
    func radarChartView(_ radarChartView: AMRadarChartView, fillColorForSection section: Int) -> UIColor
    
    /// 各グラフの枠線色を設定する
    func radarChartView(_ radarChartView: AMRadarChartView, strokeColorForSection section: Int) -> UIColor
    
    /// 各頂点の文字を設定する
    func radarChartView(_ radarChartView: AMRadarChartView, titleForVertexInRow row: Int) -> String

    /// 各頂点の文字フォントを設定する
    func radarChartView(_ radarChartView: AMRadarChartView, fontForVertexInRow row: Int) -> UIFont

    /// 各頂点の文字色を設定する
    func radarChartView(_ radarChartView: AMRadarChartView, textColorForVertexInRow row: Int) -> UIColor
}
	```
	こんな感じ
	<img width="350" alt="chart_r.png" src="https://user-images.githubusercontent.com/34936885/67146968-78c57480-f2cb-11e9-896f-4de1b13f0b82.png">

	## AMPieChartView	
	
	sectionが各項目に相当する
	
	```swift
	protocol AMPieChartViewDataSource: AnyObject {
    
    /// 扇の数を設定する
    func numberOfSections(in pieChartView: AMPieChartView) -> Int
    
    /// 各項目の値を設定する
    func pieChartView(_ pieChartView: AMPieChartView, valueForSection section: Int) -> CGFloat
    
    /// 各項目の色を設定する
    func pieChartView(_ pieChartView: AMPieChartView, colorForSection section: Int) -> UIColor
}
	```	
	
	円グラフのみ選択のアクションがある
	
	```swift
	protocol AMPieChartViewDelegate: AnyObject {
    
    /// 項目選択時に呼ばれる
    func pieChartView(_ pieChartView: AMPieChartView, didSelectSection section: Int)
    
    /// 項目選択解除時に呼ばれる
    func pieChartView(_ pieChartView: AMPieChartView, didDeSelectSection section: Int)
}
	```
	こんな感じ
	<img width="350" alt="chart_p.png" src="https://user-images.githubusercontent.com/34936885/67146931-23896300-f2cb-11e9-8dbf-84743a54f314.png">

#つくったきっかけ
ある日、「次の要望でグラフを表示するかもしれない。」と言われグラフ表示用のクラスを色々つくってみた。グラフはライブラリが充実しているので最初は公開されているものを使おうか迷ったが、時間もあったので勉強がてら自作することにした。

#使わなかった理由
そんな要望がくることはなかった...

#さいごに
今回は時間があり、細かいカスタマイズもできると思い自作したが、公開されているライブラリを利用する方がいいように思う。工数もかからないし、長い間利用されているものであればバグも少ないと思われる。

これとかすごい[charts(github:danielgindi/Charts)](https://github.com/danielgindi/Charts)

私はほぼObjective-Cしか使ったことがないペーペーのプログラマーなので記事内容やgithubのコードにおかしなところがあればご指摘いただければ幸いです。

#つくったのまとめ
* [アナログ時計を描画してみた（swift）](https://qiita.com/am10/items/0222e6966d58062d2eca)
* [スピードメーターをつくってみた（swift）](https://qiita.com/am10/items/0fe8cffac7dd7659eb2a)
* [めくるカレンダーをつくってみた(swift)](https://qiita.com/am10/items/2a929ca8196f33cb1d4a)
* [グラフを描画してみた(swift)](https://qiita.com/am10/items/aee964a8a7a9712d66f8#_reference-ca2e5485de5acf8eca97)
* [ちからわざで日本地図を描いてみた(swift)](https://qiita.com/am10/items/26de3242ee33b4bd4aae)
* [カラーピッカーをつくってみた(swift)](https://qiita.com/am10/items/82a4adb2267979841c9e)
* [面積比がそれっぽいベン図を描いてみた(swift)](https://qiita.com/am10/items/858041f70be4d8de5090)
* [UIViewを燃やしてみた（swift）](https://qiita.com/am10/items/f7b32ea5725feeb1469f)

##動作確認用にまとめたプロジェクト
* [Carthageで入れたやつ](https://github.com/adventam10/TestCarthage)
* [CocoaPodsで入れたやつ](https://github.com/adventam10/TestCocoaPods)
* [SwiftPMで入れたやつ](https://github.com/adventam10/TestSwiftPM)