Vue.js(ts)でvue-chartjsを使う

# はじめに

今までJSで何かしらのグラフを描画する時に、「Chart.js」を利用していたので、Vue.jsでも同様に「Chart.js」を使っていたのですが、今更ながら「vue-chartjs」というものを知って、触ってみて、想像以上に便利なものだったので、勝手にこの感動を共有していこうと思います。

## 作ったデモ

こんな感じのものを作りました。
![vue_chartjs_demo.gif](https://qiita-image-store.s3.amazonaws.com/0/95875/19ee5ebc-e2d4-34d1-448d-aa2d84a58875.gif)
ソースコードはgithubにあげています。
[https://github.com/ryo-is/vue-demo-sample](https://github.com/ryo-is/vue-demo-sample)

## 何がよかったか

色々ありますが特に伝えたい点は以下の3点。

* 描画ロジック自体がコンポーネントで提供されているので、`datasets` と `options` を渡せばグラフ描画してくれる
* `datasets` を更新すると、再描画してくれる
* TypeScriptからでも使いやすいように、型宣言ファイルなど整備されている

## どう実装したか

### vue-chartjsコンポーネント

グラフ描画コンポーネントのScriptはこんな感じ

```ts:script
import { Component, Mixins, Prop } from "vue-property-decorator";
import Chart from "chart.js";
import { Line, Bar, mixins } from "vue-chartjs";

@Component({})
export default class LineChartComponent extends Mixins(Line, Bar, mixins.reactiveProp) {
  @Prop() public chartData: Chart.ChartData;
  @Prop() public chartOptions: Chart.ChartOptions;

  public mounted() {
    console.log(this);
    this.renderChart(this.chartData, this.chartOptions);
  }
}
```

今回は棒グラフ(Bar)と折れ線グラフ(Line)を使いたいので、`Mixins` を利用してextendsしていきます。
また `mixins.reactiveProp` をextendsすることで、Propが更新かかればグラフ再描画してくれるようになります。

### 親コンポーネント

親コンポーネントからPropで `datasets` と `options` を渡していきます。

```pug:template
.chart
  .title {{ chartTitle }}
  el-row
    .chart-area
      el-button.change-value-button(type="primary" @click="createChartData()") データ変更
      lineChartComponent(:chart-data="chartData", :chart-options="chartOptions")
```

```ts:script
import { Component, Vue } from "vue-property-decorator";
import lineChartComponent from "@/components/chart/VueChart.vue";
import Chart from "chart.js";

const FONT_COLOR = "rgba(255, 255, 255, 1)";
const GRID_LINES_SETTING = {
  display: true,
  drawOnChartArea: false,
  color: "rgba(255, 255, 255, .5)",
  zeroLineColor: "rgba(255, 255, 255, 1)"
};

@Component({
  components: {
    lineChartComponent
  }
})
export default class ChartComponent extends Vue {
  public chartTitle: string = "Vue Chartjs Demo";
  public chartData: Chart.ChartData = {};
  public chartOptions: Chart.ChartOptions = {
    responsive: true,
    maintainAspectRatio: false,
    legend: {
      // display: false
      onClick(event, legendItem) {
        return;
      },
      fullWidth: false,
      labels: {
        boxWidth: 20,
        fontColor: FONT_COLOR
      },
    },
    layout: {
      padding: {
        top: 20,
        left: 20,
        bottom: 20,
        right: 20
      }
    },
    scales: {
      xAxes: [
        {
          gridLines: GRID_LINES_SETTING,
          ticks: {
            autoSkip: true,
            fontColor: FONT_COLOR,
            fontSize: 14
          },
          scaleLabel: {
            display: true,
            fontColor: FONT_COLOR,
            labelString: "月",
          },
        },
      ],
      yAxes: [
        {
          id: "yAxis_1",
          type: "linear",
          gridLines: GRID_LINES_SETTING,
          scaleLabel: {
            display: true,
            fontColor: FONT_COLOR,
            labelString: "湿度(%)"
          },
          ticks: {
            autoSkip: true,
            fontColor: FONT_COLOR,
            fontSize: 14,
            min: 0,
            max: 100
          },
        },
        {
          id: "yAxis_2",
          type: "linear",
          gridLines: GRID_LINES_SETTING,
          scaleLabel: {
            display: true,
            fontColor: FONT_COLOR,
            labelString: "温度(℃)"
          },
          ticks: {
            autoSkip: true,
            fontColor: FONT_COLOR,
            fontSize: 14,
            min: 0,
            max: 40
          },
          position: "right"
        }
      ],
    }
  };

  public created() {
    this.createChartData();
  }

  public createChartData() {
    this.chartData = {
      labels: ["1", "2", "3", "4", "5"],
      datasets: [
        {
          yAxisID: "yAxis_1",
          type: "line",
          label: "湿度",
          backgroundColor: "#6090EF",
          borderColor: "#6090EF",
          fill: false,
          data: this.craeteRamdomValue(100)
        },
        {
          yAxisID: "yAxis_2",
          type: "bar",
          label: "温度",
          backgroundColor: "#F87979",
          borderColor: "#F87979",
          fill: false,
          data: this.craeteRamdomValue(40)
        }
      ]
    };
  }

  public craeteRamdomValue(baseNumber: number) {
    const arr: number[] = [];
    for (let i = 0; i < 5; i++) {
      arr.push(Math.floor(Math.random() * baseNumber));
    }
    return arr;
  }
}
```

なんとグラフを描画するのに必要なソースコードはこれだけです。
これでグラフの描画をしてくれます。

## さいごに

今までなんで頑張って素のChart.jsを使っていたんだろう…と虚しくなるくらい、「vue-chartjs」は使い勝手が良いです。
もしVue.jsのアプリでグラフを描画したいなーという瞬間があれば、「vue-chartjs」おすすめです！
ではまた！！！