Vueでグラフ描画するなら、Google Chartがオススメ

# はじめに
これはVue Advent Calendar 2019 5日目の記事です。

最近、Vue.jsで集計結果をグラフ描画する機会がありました。
`Vue グラフ描画`で調べると基本的にCharts.jsが出てきます。
色々、考えt時に、Google chartsが便利だったので紹介したいと思います。

## google chartsとは
[google charts](https://developers.google.com/chart)とは、googleの図表描画ライブラリです。
スプレッドシートとかで使われているグラフを描画できるイメージです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106459/565ea660-18e1-71db-a36d-d8d7ea70d82e.png" width="80%">


## プロジェクト作成

- 素のVue.jsではなく、Nuxt.jsでやっていたためNuxtでプロジェクト作成

```bash
yarn create nuxt-app charts-sample
# yarnを選択
# cssフレームワークはbulmaを選択
cd charts-sample
yarn dev
```

## インストール

Google chartsのVue向けWrapperの[vue-google-charts](https://github.com/devstark-com/vue-google-charts)です。

```bash
yarn add vue-google-charts
```

- iconを読みこませたいので、google iconを追加

```javascript:nuxt.config.js
（省略）
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
      // 下記を追加
      { href: 'https://fonts.googleapis.com/icon?family=Material+Icons', rel: 'stylesheet' }
    ]

```

## グラフコンポーネント
- グラフの種類とデータ、オプションを渡してあげると描画してくれるようにしています。
<img width="500" alt="piechart.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106459/da6f3b50-7e1a-a22b-1524-c21a8e2a4ca6.png">


```vuejs:components/atoms/Chart.vue
<template>
  <GChart
    :type="chartType"
    :data="chartData"
    :options="chartOptions"
    :createChart="
      (el, google, type) => {
        return new google.visualization[type](el)
      }
    "
  />
</template>

<script>
import { GChart } from 'vue-google-charts'

export default {
  components: {
    GChart
  },
  props: {
    chartType: {
      type: String,
      default: ''
    },
    chartData: {
      type: Array,
      default: () => {
        return []
      }
    },
    chartOptions: {
      type: Object,
      default: () => {
        return {}
      }
    }
  }
}
</script>
```

```vuejs:pages/index.vue
<template>
  <div class="container">
    <chart
      :chartType="chartType"
      :chartData="chartData"
      :chartOptions="chartOptions"
    />
  </div>
</template>

<script>
import Chart from '@/components/atoms/Chart.vue'

export default {
  components: {
    Chart,
    Dropdown
  },
  data() {
    return {
      chartType: 'PieChart',
      chartData: [
        ['年', '売上', '費用', '収益'],
        ['2014', 1000, 400, 200],
        ['2015', 1170, 460, 250],
        ['2016', 660, 1120, 300],
        ['2017', 1030, 540, 350]
      ],
      chartOptions: {
        title: '会社の損益',
        subtitle: '売上',
        width: 500,
        height: 500
      }
    }
  }
}
</script>
```

## 100%積み上げ棒グラフを描画
<img width="500" alt="100barchart.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106459/82db1426-ced7-fdbc-c612-aadc431dd3ec.png">


- chartOptionに`isStacked: 'percent'`を追加する

```javascript

      chartOptions: {
        title: '会社の損益',
        subtitle: '売上',
        width: 500,
        height: 500,
        isStacked: 'percent'
      }
```


## アノテーションを付ける
- グラフを描画していると、グラフに数値を表示したくなります。
<img width="500" alt="100barchartannotation.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106459/9a84ee97-d8cd-1c9d-4f31-3bfce11a153c.png">

```vuejs:components/atoms/ChartWithAnnotation.vue
<template>
  <GChart
    :type="chartType"
    :data="data"
    :options="chartOptions"
    :createChart="
      (el, google, type) => {
        return new google.visualization[type](el)
      }
    "
    @ready="onChartReady"
  />
</template>

<script>
import { GChart } from 'vue-google-charts'

export default {
  components: {
    GChart
  },
  props: {
    chartType: {
      type: String,
      default: ''
    },
    chartData: {
      type: Array,
      default: () => {
        return []
      }
    },
    chartOptions: {
      type: Object,
      default: () => {
        return {}
      }
    }
  },
  data() {
    return {
      viewOption: {
        calc: 'stringify',
        type: 'string',
        role: 'annotation'
      },
      data: null
    }
  },
  methods: {
    onChartReady(chart, google) {
      console.log('annotation')
      this.addValueLabel(chart, google)
    },
    addValueLabel(chart, google) {
      const dataArr = this.chartData
      const data = google.visualization.arrayToDataTable(dataArr)

      const formatPercent = new google.visualization.NumberFormat({
        pattern: '#,##0.0%'
      })

      const view = new google.visualization.DataView(data)
      const viewColumn = []
      const sumObj = this.calcTotal(dataArr)
      dataArr[0].forEach((val, i) => {
        viewColumn.push(i)
        if (i !== 0) {
          const viewOption = JSON.parse(JSON.stringify(this.viewOption))
          viewOption.sourceColumn = i

          viewOption.calc = (dt, row) => {
            const amount = dt.getValue(row, i) / sumObj[row]
            return formatPercent.formatValue(amount)
          }
          viewColumn.push(viewOption)
        }
      })
      view.setColumns(viewColumn)
      chart.draw(view, this.chartOptions)
    },
    calcTotal(dataArr) {
      const sumObj = {}
      dataArr.forEach((arr, i) => {
        // 1行目はヘッダーなので飛ばす
        if (i !== 0) {
          sumObj[i - 1] = 0
          arr.forEach((val, j) => {
            // 2行目以降の1カラム目はタイトルなので飛ばす
            if (j !== 0) {
              sumObj[i - 1] += Number(val)
            }
          })
        }
      })
      return sumObj
    }
  }
}
</script>
```
- アノテーションのフォーマットは、下記のように指定しています。
- パターンを変えれば数値やパーセント表示以外でも表示することが可能です。

```javascript
      const formatPercent = new google.visualization.NumberFormat({
        pattern: '#,##0.0%'
      })
```

## 最後に
- google-chartsの紹介でした。

### google chartsの良いところ
- グラフが豊富
- データ構造が同じで複数のグラフを描画できる
- アノテーションなど拡張性が高い（別途拡張用のライブラリとか不要）

主観ですがデザインはデフォルトだと少しダサいなと感じますw

昨今、データの分析結果、集計結果の可視化がトレンドなので、vue × google chartで簡単にグラフ描画が可能なので、触ってみてください。
今回のソースコードは、[ここに](https://github.com/tai-hatake/nuxt-google-charts-sample)あがってます。

明日は@daikidsさんです。