最初に
vue-chartjs は Chart.js をvueで使用するためのラッパーです。 再利用可能なチャートコンポーネントを簡単に作成できます。
初めに
vue-chartjs
あまり手間をかけずにvueの中でchart.jsを使うことができます。 シンプルなチャートをできるだけ早く起動して実行したいという人に最適です。
chart.jsの基本ロジックを抽象化していますが、公開されたchart.jsのオブジェクトを使用して柔軟にカスタマイズできます。
インストール
NPM
npm
を使って vue-chartjs
をインストールすることができます。 ただしプロジェクトへの依存関係として chart.js
を追加する必要があります。 なぜなら Chart.js
はpeerDependencyだからです。 このため、Chart.jsのバージョンを完全に制御できます。
yarn add vue-chartjs chart.js@2.9.4
or npm install vue-chartjs chart.js@2.9.4 --save
TIP
Vue.jsの Version 1.xを使用している場合はlegacy
タグを使用してください。しかし、vueのバージョン1はもうメンテナンスされません。
yarn add vue-chartjs@legacy
ブラウザ
ブラウザから直接 vue-chartjs
を使用することができます。 先にChart.js
スクリプトを追加してからvue-chartjs
スクリプトを追加してください
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
<script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.min.js"></script>
統合
Chart.js
で利用可能なすべてのチャートタイプは名前付きコンポーネントとしてエクスポートされ、そのままインポートすることができます。 これらのコンポーネントは通常のVueコンポーネントですが、それを拡張
する必要があります。
vue-chartjs
の背後にある考え方は、最大限の柔軟性と拡張性を持ち、使いやすいコンポーネントを提供することです。 これを実現するには、独自の Chart Component を作成し、それをvue-chartjs
コンポーネントして提供するように拡張する必要があります。
拡張することで、チャートコンポーネントのメソッドとロジックは、独自のチャートコンポーネントにマージされます。
最初のチャートの作成
BaseChartをインポートしてextendします。この方法で異なるデータのチャートを表示するときに柔軟性が大幅に向上します。 コンポーネントをカプセル化し、プロパティを使用してコンポーネント内のデータに渡したり、コンポーネント内に直接データを記述することができます。ただし直接コンポーネント内にデータを記述した場合は再利用ができません。
パッケージ全体または各モジュールを個別にインポートできます。 インポートしたものを extends:
か mixins:[]
を使って指定します。 また mounted()
フックで、 this.renderChart()
を呼び出します。 これでチャートインスタンスが作成されます。
import { Bar } from 'vue-chartjs'
export default {
extends: Bar,
mounted () {
this.renderChart(data, options)
}
}
TIP
extends: Bar
または mixins: [Bar]
どちらの記述方法でも使用できます。
メソッドthis.renderChart()は、Barコンポーネントによって提供され、2つのパラメータを受け付けています。 どちらもObject
です。 最初のものは表示するデータで、二番目のものはオプションを格納するオブジェクトです。
チャート毎に必要なオブジェクト構造は公式 Chart.js docsをチェックしてください。
Vue シングルファイルコンポーネント
本ドキュメントのほとんどの例はjavascriptファイルを基に記述されていて、 .vue
ファイルの例はありません。 これはあなたが、たいてい必要なのは <script>
ブロックだけだからです。 もちろん .vue
ファイルを使うこともできます。
Chart.vue
<script>
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: ['chartdata', 'options'],
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
</script>
<style>
</style>
Template タグはマージできません
.vue
ファイルに<template>
タグを含めないでください。 Vueはテンプレートをマージすることはできません。.vue
ファイルに空の <template>
タグを追加すると、Vueは拡張されたものからではなく.vue
のコンポーネントからテンプレートを取得します。その結果、空のテンプレートとエラーが発生します。
チャートデータの更新
Chart.js 自身ではデータセットを変更した場合に、ライブアップデートの機能を提供していません。 しかしvue-chartjs
はこれを実現するために2つの mixin を提供します。
reactiveProp
reactiveData
両方のミックスインは実際には同じ結果を達成します。 ほとんどの場合は、reactiveProp
を使います。 このミックスインはチャートコンポーネントのロジックを拡張し、自動的に chartData
という名前のプロパティを作成し、このプロパティにvue watch
を追加します。 データが変更されると、データセット内のデータだけが変更されていれば update()
を、新しいデータセットが追加されていれば renderChart()
を呼び出します。
ractiveData
はプロパティではないローカルのchartData変数を作成し、Watcherを追加します。 これは単一目的のチャートが必要でチャートコンポーネント内でAPI呼び出しを行う場合にのみ役に立ちます。
例
LineChart.js
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
props: ['options'],
mounted () {
// this.chartData is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.chartData, this.options)
}
}
RandomChart.vue
<template>
<div class="small">
<line-chart :chart-data="datacollection"></line-chart>
<button @click="fillData()">Randomize</button>
</div>
</template>
<script>
import LineChart from './LineChart.js'
export default {
components: {
LineChart
},
data () {
return {
datacollection: null
}
},
mounted () {
this.fillData()
},
methods: {
fillData () {
this.datacollection = {
labels: [this.getRandomInt(), this.getRandomInt()],
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
data: [this.getRandomInt(), this.getRandomInt()]
}, {
label: 'Data One',
backgroundColor: '#f87979',
data: [this.getRandomInt(), this.getRandomInt()]
}
]
}
},
getRandomInt () {
return Math.floor(Math.random() * (50 - 5 + 1)) + 5
}
}
}
</script>
<style>
.small {
max-width: 600px;
margin: 150px auto;
}
</style>
イベント
データが変更されると、リアクティブミックスインはイベントを発行します。 チャートコンポーネントの v:on
でそれらを受け取ることができます。 以下のイベントがあります。
chart:render
- ミックスインが完全にレンダリングしたときchart:destroy
- ミックスインがチャートオブジェクトインスタンスを削除したときchart:update
- ミックスインが再レンダリングの代わりに更新をしたときlabels:update
- labelsがセットされたときxlabels:update
- xLabelsがセットされたときylabels:update
- yLabelsがセットされたとき
トラブルシューティング
現状でのリアクティブシステムは頑強ではありません。 データを渡すためのユースケースや方法が多数あるため、それにはいくつかの問題が発生することがあります。
オプション
options
オブジェクトは今のところリアクティブではありません。 そのため、チャートのオプションを動的に変更しても、それらはミックスインによって認識されません。
ミックスインを使用している場合は、options
というプロパティとしてオプションを渡す必要があります。 mixinがchart.jsのupdate()
メソッドを呼び出すか、新しいチャートを破棄して描画する際に、これは重要です。 ミックスインが新しいチャートを描画するとき、this.renderChart(this.chartData、this.options)
を呼び出します。
しかし、オプションを mounted()
フックで直接渡すと、それらは失われます。
間違った方法
import { Line, mixins } from 'vue-chartjs'
export default {
components: { Line }
mixins: [mixins.reactiveProp],
mounted () {
this.renderChart(this.chartData, {responsive: true})
}
}
正しい方法
import { Line, mixins } from 'vue-chartjs'
export default {
components: { Line }
mixins: [mixins.reactiveProp],
mounted () {
this.renderChart(this.chartData, this.options)
}
}
独自のウォッチャー
(新しいデータをプッシュするのではなく)データをたくさん変更するのであれば、独自のウォッチャーを実装するのが一番良いやり方です。 必要に応じて、自分で this.$data._chart.update()
または this.renderChart()
を呼び出すことができます。
シンプルなwatcherの実装例:
watch: {
chartData () {
this.$data._chart.update()
}
}
例
propsを使用したチャート
目標は再利用可能なチャートコンポーネントを作成することです。 この目的のためには、オプションとチャートデータをVue.jsの props として渡す必要があります。 このようにすることで、チャート自体はデータの取得については気にせず、表示のみに注力できます。
まずコンポーネントを作成します。
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: {
chartdata: {
type: Object,
default: null
},
options: {
type: Object,
default: null
}
},
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
その後、作成したチャートコンポーネントを親コンポーネントに追加できます。
<line-chart :chartdata="chartData" :options="chartOptions"/>
ローカルデータを使用したチャート
独自のチャートコンポーネントでチャートデータを直接扱うことができます。 コンポーネント内のチャートデータを renderChart()
メソッドに渡すだけです。
import { Bar } from 'vue-chartjs'
export default {
extends: Bar,
data: () => ({
chartdata: {
datacollection: {
labels: ['January', 'February'],
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
data: [40, 20]
}
]
}
},
options: {
responsive: true,
maintainAspectRatio: false
}
}),
mounted () {
this.renderChart(this.datacollection, this.options)
}
}
APIから取得したデータを用いたチャート
一般的にはデータを取得するためにAPIを使用するのがパターンでしょう。しかし留意すべきことがいくつかあります。 最も一般的な問題は、チャートコンポーネントを直接マウントし、非同期API呼び出しからデータを渡すことです。 このアプローチでの問題点は、chart.jsがチャートをレンダリングしてチャートデータにアクセスしようとしますが、API呼び出しが非同期だということです。 この時、データが到着する前にあなたはチャートを表示しようとしてしまいます。
これを防ぐには、単純な v-if
が最善の解決策です。
データプロパティとオプションプロパティを使用してチャートコンポーネントを作成すると、コンテナコンポーネントからデータとオプションを渡すことができます。
Chart.vue
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: {
chartdata: {
type: Object,
default: null
},
options: {
type: Object,
default: null
}
},
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
それから、あなたのAPIコールまたはVuex接続を処理するコンテナコンポーネントを作成します。
ChartContainer.vue
<template>
<div class="container">
<line-chart
v-if="loaded"
:chartdata="chartdata"
:options="options"/>
</div>
</template>
<script>
import LineChart from './LineChart.vue'
export default {
name: 'LineChartContainer',
components: { LineChart },
data: () => ({
loaded: false,
chartdata: null
}),
async mounted () {
this.loaded = false
try {
const { userlist } = await fetch('/api/userlist')
this.chartData = userlist
this.loaded = true
} catch (e) {
console.error(e)
}
}
}
</script>
動的スタイルを使用したチャート
あなたは responsive:true
をセットして外側のdivにインラインスタイルとして適用されるstylesオブジェクトを渡すことができます。 これにより、外側のコンテナの高さと幅を動的に変更できます。 これはchart.jsのデフォルトの動作ではありません。 これには計算プロパティを使用するのが最善です。
WARNING
position: relative
をセットする必要があります。
<template>
<div>
<line-chart :styles="myStyles"/>
<button @click="increase()">Increase height</button>
</div>
</template>
<script>
export default {
data () {
return {
height: 300
}
},
methods: {
increase () {
this.height += 10
}
},
computed: {
myStyles () {
return {
height: `${this.height}px`,
position: 'relative'
}
}
}
}
</script>
Custom / New Charts
場合によっては、デフォルトのChart.jsに用意されているチャートを拡張する必要があります。 デフォルトチャートを拡張および変更する方法、あるいは独自のチャートタイプを作成する方法は、たくさんの例があります。
vue-chartjs
でも、これとほぼ同じ方法で行うことができます。
// 1. Import Chart.js so you can use the global Chart object
import Chart from 'chart.js'
// 2. Import the `generateChart()` method to create the vue component.
import { generateChart } from 'vue-chartjs'
// 3. Extend on of the default charts
// http://www.chartjs.org/docs/latest/developers/charts.html
Chart.defaults.LineWithLine = Chart.defaults.line;
Chart.controllers.LineWithLine = Chart.controllers.line.extend({ /* custom magic here */})
// 4. Generate the vue-chartjs component
// First argument is the chart-id, second the chart type.
const CustomLine = generateChart('custom-line', 'LineWithLine')
// 5. Extend the CustomLine Component just like you do with the default vue-chartjs charts.
export default {
extends: CustomLine,
mounted () {
// ....
}
}
リソース
vue-chartjs
の使い方に関するチュートリアルのようないくつかのリソースがあります。