Vue Chart.jsの使い方

はじめに

Vue.jsを使ったプロジェクトでチャートを表示させたいとき、vue-chart.jsというオープンソースライブラリが便利です。

スクリーンショット 2020-05-31 10.10.10

vue-chart.jsはChart.jsをラッパーしています。どんなチャートが描画できるかは下記サイトを見てみてください。

インストール

Vue.jsのプロジェクトにyarnかnpmでインストールしてください。

// yarn
yarn add vue-chartjs chart.js

// npm
npm install vue-chartjs chart.js --save

基本の使い方

東京都の1日の気温をチャートにしてみました。

<script>
import { Line } from 'vue-chartjs';

export default {
 extends: Line,
 name: 'LineChart',
 data:() => ({
   chartdata: {
     labels: ["12:00", "15:00", "18:00", "21:00", "0:00", "3:00", "6:00", "9:00"],
     datasets: [
       {
         label: 'temperature',
         data: [23, 25, 22, 20, 19, 19, 19, 20, 23]
       }
     ]
   },
   options: {
     responsive: true,
     maintainAspectRatio: false
   }
 }),
 mounted () {
   this.renderChart(this.chartdata, this.options);
 },
}
</script>

vue-chartをimportし、extendsするチャートを指定します。今回はLineを指定しました。

スクリーンショット 2020-05-31 12.09.20

表示をカスタマイズ

チャートが表示されましたが、下記の問題点があります。

・灰色で表示されている
・Y軸が0から始まっていない(19〜になっている)
・気温なので、「℃」と単位をつけたい

そこで下記のようにコードを修正しました。

<script>
import { Line } from 'vue-chartjs';

const setDegreeCelsius = (value, index, values) => {
 return `${value}℃`
}
export default {
 extends: Line,
 name: 'LineChart',
 data:() => ({
   chartdata: {
     labels: ["12:00", "15:00", "18:00", "21:00", "0:00", "3:00", "6:00", "9:00"],
     datasets: [
       {
         label: 'temperature',
         data: [23, 25, 22, 20, 19, 19, 19, 20, 23],
         borderColor: 'rgba(255, 146, 51, 1)',
         backgroundColor: 'rgba(255, 146, 51, 0.2)',
       }
     ]
   },
   options: {
     scales: {
         yAxes: [{
             ticks: {
                 beginAtZero: true,
                 callback: function(value, index, values) {
                     return setDegreeCelsius(value, index, values);
                 }
             }
         }]
     },
     responsive: true,
     maintainAspectRatio: false
   }
 }),
 mounted () {
   this.renderChart(this.chartdata, this.options);
 }
}
</script>
色を表示・・・borderColorとbackgroundColorにrgbaを指定(4行目)
Y軸を0から表示・・・beginAtZero: trueにする(28行目)
単位をつける・・・setDegreeCelsiusを指定(30行目)

これでチャートがこのように表示されました。

スクリーンショット 2020-05-31 12.29.51

ローディングを実装

実際にチャートを表示する際はAPIからデータを取得することが殆どだと思います。データ取得中はチャート部分にローディングを表示させたいと思います。

JSON Serverを使って、APIモックサーバーを用意します。セットアップ詳細はこちらの記事を見てみてください。

apiディレクトリを作成し、data.jsonを作ります。

{
   "chartData": {
       "labels": [
           "12:00", "15:00", "18:00", "21:00", "0:00", "3:00", "6:00", "9:00"
       ],
       "temperature": [
           23, 25, 22, 20, 19, 19, 19, 20, 23
       ]
   }
}

起動のためpackage.jsonのscriptsに下記を追加すると便利です。(--delayオプションを付けることで、ローディングのテストがしやすくなります)

"start": "json-server api/data.json --delay 2000"

yarn starするとターミナルにはこのように表示されます。

スクリーンショット 2020-05-31 12.46.07

作成したAPIからfetchする処理を追加します。

<template>
 <div class="container">
   <LineChart
     v-if="loaded"
     :chartdata="chartdata"
     :options="options"/>
   <VueLoading v-else type="bars" color="rgb(255, 146, 51)" :size="{ width: '50px', height: '50px' }"/>
 </div>
</template>

...中略

  async mounted () {
   const url = 'http://localhost:3000/chartData';
   this.loaded = false
     try {
       const response = await fetch(url);
       const chartData = await response.json();
       const chartdata = this.createChartdata(chartData.temperature, chartData.labels);
       this.chartdata = chartdata;
       this.loaded = true
     } catch (e) {
       console.error('error', e)
     }
 },
 methods: {
   createChartdata(data, labels) {
     const chartdata = {
       labels: labels,
       datasets: [
         {
           label: 'temperature',
           data: data,
           borderColor: 'rgba(255, 146, 51, 1)',
           backgroundColor: 'rgba(255, 146, 51, 0.2)',
         }
       ]
     }
     return chartdata;
   }
 }

これでローディングバーが表示され、データ取得後にチャート表示することができます。

スクリーンショット 2020-05-31 14.06.58

スクリーンショット 2020-05-31 14.02.02

余談ですが、ローディングは下記のライブラリを使わせてもらいました。

こんな種類がありました。

スクリーンショット 2020-05-31 14.10.56

他にもChart.jsには色んな種類のチャートを表示することができるので、公式サイトを見てみてください。

スクリーンショット 2020-05-31 14.19.12

参考


いいなと思ったら応援しよう!

sumi
スキ頂けると嬉しいです〜