【Swift】Chartsでオシャレなグラフを描画してみる( 棒グラフ編 )

# はじめに
[Charts](https://github.com/danielgindi/Charts)というライブラリはご存知でしょうか？
とても有名なライブラリで、iOSでグラフを描画しようと思ったことがある人なら聞いたことや使ったことがあると思います。

Chartsはグラフ自体を非常に細かくカスタマイズすることができる素晴らしいライブラリです✨
今回は忘備録も兼ねてChartsを使って今時でオシャレな棒グラフを作ってみたいと思います。

# オシャレな棒グラフって？
普段実装ばかりでデザインのことには疎いので、
まずは今時でオシャレな棒グラフのデザインを[Dribbble](https://dribbble.com/)や[Behance](https://www.behance.net/)で調査してみました。
その結果以下のような棒グラフが流行っているような感じがしました。
Figmaでパパッと作ったので数値などは適当です。

| Y軸の値表示なし | Y軸の値表示あり |  
| :---------: | :----------: |  
| ![Bar chart ( disable grid ).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/a059895c-4ff9-eb99-4cc2-6d7e7ca2cf2c.png) | ![Bar chart ( enable grid ).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/c2aebe32-5c11-4810-908e-bec892765791.png)|

ポイントをまとめるとこんな感じになりました。

1. X軸の縦線は表示しない
2. バーの右上と左上は角丸
3. グラフの平均を表す線があって、点線で表示
4. Y軸の値を他のラベルなどに表示する場合はグラフに表示しない

4は以下のようなUIの場合、グラフにはY軸の値を表示しない代わりに、グラフをタップするとグラフの上に表示されているラベルにY軸の値が表示されるようなイメージです。

<img width="480" alt="スクリーンショット 2020-01-14 15.29.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/12d01ae0-73d7-d8b6-3f0f-fc6703da5f36.png">

早速作っていきたいところですが、一点問題があります。

# 棒グラフの角丸はサポートされていない
**現在、Chartsでは棒グラフの角丸はサポートされていません。**
[PR](https://github.com/danielgindi/Charts/pull/3754)は存在しますが、色々問題があってマージされていない状態です。

さすがにフォークして直すのは時間がかかりそうだったので、角丸は省略したものを作成します。
個人的には角丸がなくても結構それっぽくなるので、これはこれでありだと思っています。

# 実際に作ってみる
それでは実際に作っていきます。

## Chartsのインストール
ChartsはCocoaPodsとCarthageに対応しています。
自分はCarthageでインストールしました。詳しくは公式の[Carthage Install](https://github.com/danielgindi/Charts#carthage-install)を参考にしてください。

## BarChartViewを追加する
Chartsのグラフを描画する`ChartView`は**Interface Builder**に対応しているのでStoryboardから追加することができます。

今回は棒グラフを描画したいので一枚`UIView`を用意して、**Custom Class**に`BarChartView`、**Module**に`Charts`を設定します。

![スクリーンショット 2020-01-15 16.12.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/386cb1bb-0e47-f580-7518-f62a00f2daeb.png)

あとはいつも通りViewControllerにOutlet接続すればコードでいじれるようになります。

```Swift
import UIKit
import Charts

class ViewController: UIViewController {

    @IBOutlet weak var barChartView: BarChartView!

    // ...
}
```

## グラフに表示するデータについて
Chartsでは表示するデータを`ChartData`に変換する必要があります。
変換した`ChartData`を`ChartView`のもつ`data`プロパティにセットすることでデータが描画されます。
以下では適当な`Int`の配列を`BarChartData`に変換してグラフに表示しています。

```Swift
let rawData: [Int] = [20, 50, 70, 30, 60, 90, 40]
let entries = rawData.enumerated().map { BarChartDataEntry(x: Double($0.offset), y: Double($0.element)) }
let dataSet = BarChartDataSet(entries: entries)
let data = BarChartData(dataSet: dataSet)
barChartView.data = data
```

デフォルトの状態でこれを表示するとこんな感じになります。

| デフォルト |
| :-----: |
|<img width="292" alt="スクリーンショット 2020-01-15 16.26.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/4c9d8fdc-45ab-fe90-fe0d-79b2fff84e90.png"> |

## X座標軸の設定
X座標軸関連の設定は`xAxis`プロパティに対して設定します。
デフォルトの状態では余分な線などが表示されていたりするので、X軸のラベルの位置、軸の線の表示、グリッドの非表示を行っています。

```Swift
// X軸のラベルの位置を下に設定
barChartView.xAxis.labelPosition = .bottom
// X軸のラベルの色を設定
barChartView.xAxis.labelTextColor = .systemGray
// X軸の線、グリッドを非表示にする
barChartView.xAxis.drawGridLinesEnabled = false
barChartView.xAxis.drawAxisLineEnabled = false
```

## 右側のY座標軸の設定
Y座標軸は左右それぞれ設定することができます。
右側のY座標軸関連の設定は`rightAxis`プロパティに設定します。
今回は右側のY座標軸は表示しないので無効にします。

```Swift
// 右側のY座標軸は非表示にする
barChartView.rightAxis.enabled = false
```

## 左側のY座標軸の設定
左側のY座標軸関連の設定は`leftAxis`プロパティに設定します。
ここはY軸の値を表示するかしないかで変わってきますが、とりあえずY軸の値を表示したパターンを作成します。

デフォルトではY座標の最小値がグラフに表示しているデータによって決定されてしまうので、`axisMinimum`に0を設定して0始まりになるように設定したり、ラベルの色や数、グリッドや軸線の表示に関する設定をしています。

```Swift
// Y座標の値が0始まりになるように設定
barChartView.leftAxis.axisMinimum = 0.0
barChartView.leftAxis.drawZeroLineEnabled = true
barChartView.leftAxis.zeroLineColor = .systemGray
// ラベルの数を設定
barChartView.leftAxis.labelCount = 5
// ラベルの色を設定
barChartView.leftAxis.labelTextColor = .systemGray
// グリッドの色を設定
barChartView.leftAxis.gridColor = .systemGray
// 軸線は非表示にする
barChartView.leftAxis.drawAxisLineEnabled = false
```

## 凡例の設定
デフォルトではグラフの凡例が表示されているので非表示にします。

```Swift
barChartView.legend.enabled = false
```

## 平均の線の設定
平均の線は`LimitLine`を使って表示します。
以下では線の色と点線の設定を行っています。`lineDashLengths`は複数の値を入れることで不規則な形の点線を作ることも可能です。

```Swift
let avg = rawData.reduce(0) { return $0 + $1 } / rawData.count
let limitLine = ChartLimitLine(limit: Double(avg))
limitLine.lineColor = .systemOrange
limitLine.lineDashLengths = [4]
barChartView.leftAxis.addLimitLine(limitLine)
```

※ `LimitLine`は`leftAxis`もしくは`rightAxis`に対して追加するので、追加する対象の`enable`が`false`になっていると表示されないので注意してください。

ここまでで以下のような見た目になりました。だいぶそれっぽくなったと思います。

| デフォルト | 設定後 |
| :-----: | :---: |
| <img width="292" alt="スクリーンショット 2020-01-15 16.26.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/a8492cea-6dd3-0305-4f8f-f7498ce0ae1c.png"> | <img width="294" alt="スクリーンショット 2020-01-16 10.04.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/4897ddf0-9dec-97e0-0652-28607908fd79.png"> |

## 棒グラフの色と値の表示の設定
最後に棒グラフの色とグラフの上に値が表示しないように設定します。
これらの設定は`ChartDataSet`に対して設定します。

```Swift
let dataSet = BarChartDataSet(entries: entries)
dataSet.drawValuesEnabled = false
dataSet.colors = [.systemBlue]
```

以上で完成です。
最終的にこんな感じになりました。

| デフォルト | 完成形 |
| :-----: | :---: |
| <img width="292" alt="スクリーンショット 2020-01-15 16.26.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/a8492cea-6dd3-0305-4f8f-f7498ce0ae1c.png"> | <img width="292" alt="スクリーンショット 2020-01-16 10.26.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202306/b94626fc-38d1-d909-3acb-89709acf4f90.png"> |

# さいごに
Chartsで今時でオシャレな棒グラフを作ってみましたがいかがだったでしょうか？
他にもグラフをアニメーションさせたり、ハイライトした時にマーカーを表示できたり、X軸のラベルの表示をカスタマイズできるなど、まだまだカスタマイズできるので気になった方はぜひ試してみてください。[公式のサンプル](https://github.com/danielgindi/Charts/tree/master/ChartsDemo-iOS/Swift)で一通り使い方はマスターできると思います。

また、今回作ったグラフはサンプルとして[QiitaChartsSample](https://github.com/hayabusabusa/QiitaChartsSample)にあげてあるので、よければ参考にしてください。

分かりにくい部分や間違いがあれば指摘していただけると嬉しいです🙇‍♂️
最後まで読んでいただきありがとうございました。