📈

Vue3 + TS + Chart.js

2023/03/11に公開3

Chart.jsとは

https://www.chartjs.org/docs/latest/

Chart.jsとは棒グラフ、折れ線グラフ、レーダーチャートなど、様々なグラフに関する描画を楽チンにしてくれるライブラリです。

今回は2023/03/11時点で最新のChart.js(4.2.1)と、Vue3、TypeScriptでレーダーチャートを実装したので、少しご紹介です。

install

まずコマンドを利用してChart.jsvue-chartjs@types/chart.jsをインストールします。
これは3つで1セットなのでinstallしていきましょ!!

pnpm install Chart.js
pnpm install vue-chartjs
pnpm install @types/chart.js -D

これでpackage.jsonに追加されたことを確かめます。

コンポネント作成

続いては、vueでchartのコンポネントを作成していきます。
今回はradar-chartを作っていきます。
https://www.chartjs.org/docs/latest/charts/radar.html

他にも種類はたくさんあります。
https://github.com/chartjs/Chart.js/tree/master/docs/charts

components/chart.vue
<script setup lang="ts">
// @types/chart.jsの型付けを使用するためにimportしてます。
import type { ChartData, ChartOptions } from 'chart.js';

// それぞれの部品をインポートしていきます。
// まだ種類があると思いますが、とりあえず手当たり次第importしておきます。
import {
  Chart as ChartJS,
  Title,
  Tooltip,
  Legend,
  BarElement,
  CategoryScale,
  LinearScale,
  PointElement,
  RadialLinearScale,
  Filler,
  LineElement
} from 'chart.js'

// 今回はRadar-chartを作成するので、import。
// 他にも{ Bar }など、種類があります。
import { Radar } from 'vue-chartjs'

// ここでChartJSでこれらを使います〜と登録してあげます。
ChartJS.register(CategoryScale, LinearScale, BarElement,PointElement ,RadialLinearScale, LineElement, Filler, Title, Tooltip, Legend)

// ここではchartに使うdataを登録していきます。
// ChartData<'radar'>でRadar-Chartの型付けを使ってます。
// 他にも<"bar">などがあります。
const data:ChartData<'radar'> = {
  labels: [
    'Eating',
    'Drinking',
    'Sleeping',
    'Designing',
    'Coding',
    'Cycling',
    'Running'
  ],
  datasets: [
    {
      label: 'My First dataset',
      backgroundColor: 'rgba(179,181,198,0.2)',
      borderColor: 'rgba(179,181,198,1)',
      pointBackgroundColor: 'rgba(179,181,198,1)',
      pointBorderColor: '#fff',
      pointHoverBackgroundColor: '#fff',
      pointHoverBorderColor: 'rgba(179,181,198,1)',
      data: [65, 59, 90, 81, 56, 55, 40]
    },
    {
      label: 'My Second dataset',
      backgroundColor: 'rgba(255,99,132,0.2)',
      borderColor: 'rgba(255,99,132,1)',
      pointBackgroundColor: 'rgba(255,99,132,1)',
      pointBorderColor: '#fff',
      pointHoverBackgroundColor: '#fff',
      pointHoverBorderColor: 'rgba(255,99,132,1)',
      data: [28, 48, 40, 19, 96, 27, 100]
    }
  ]
};

// ここではchartに使うoptionsを登録していきます。
// ChartOptions<'radar'>でRadar-Chartの型付けを使ってます。
// 他にも<"bar">などがあります。
const options:ChartOptions<'radar'> = {
  responsive: true,
  maintainAspectRatio: false
};
</script>

<template>
  <!-- 定義したdataとoptionsを渡してあげます。 -->
  <Radar :data="data" :options="options"/>
</template>
view/home.vue
<script setup lang="ts">
import Chart from "../components/Chart.vue";
</script>

<template>
  <Chart />
</template>

上記コードを書いたら、写真のように描画されます。


Radar-Chart

最後に

今回はデータも静的で、とりあえず描画するといった方法をご紹介しました。
次はここに動的にデータを入れていく(APIを叩いて入れるなど)グラフを作っていけたらと思います。
また、それが出来次第、記事にしていこうかなと思います。

Discussion

zhujunsanzhujunsan

Do you now know how to update the chart data?
I used almost the same code, I can draw chart, but when I change the data, the chart doesn't update.
The doc says I don't need to do anything as data changes have been monitored but it didn't work.
Now after date change, I can only use the ugly v-if way to refresh the chart...

tatatsurutatatsuru

Hello!
Thank you for taking a look at the article.

Do you mean that you now want to rewrite the data you draw by switching tabs, etc.?
If so, you may be able to use the code myChart.value.destroy();.

for example,

watch((tab), async() => {
  disabledFlag.value = !disabledFlag.value

  myChart.value.destroy();

  await getGanttCSV()

  await getMetaCSV(tab.value.toUpperCase())

  console.log(useMetaData.$state.useGanttMetaData)

  let ctx: HTMLCanvasElement | null = document.getElementById("myChart") as HTMLCanvasElement;
  if (ctx) myChart.value = new Chart(ctx, myChartData);


  setTimeout(() => {
    disabledFlag.value = !disabledFlag.value
  }, 1000);
})

By executing myChart.value.destroy(); and resetting the drawing once before writing the drawing process, subsequent drawings may work.

I also wrote an article at the following URL with more details, please take a look
https://zenn.dev/tatausuru/articles/3650c5fb0d9110

zhujunsanzhujunsan

thanks for replying.

i update the chart data which i think should update coresponding chart, but the data change won't trigger chart update.

and if i use v-if to hide chart and in next tick show chart again, the chart is rendered using the latest data.

it's a dirty hack so i wondering what is the proper way. (I also don't know how to use $refs in vue3+ts so i can use chart.update() to trigger a update🙃)

my code is here if you wanna take a look