株式会社スタメンでWebフロントエンド・サーバーサイドの開発をしています、河井と申します。 本記事では react-chartjs-2 の使い方についての解説をします。React でグラフを書くことになったけど始め方が分からないなどといったときに参考にしていただければ幸いです。
TL;DR (概要)
グラフ描画のためのライブラリである Chart.js を React のコンポーネントとして利用できるようになるライブラリ、react-chartjs-2 の解説記事です。グラフに表示するデータをインタラクティブに切り替えたり、図を綺麗に見せるために Plugin を用いた実装を解説します。
グラフの描画
前提として、紹介するライブラリは既にインストールされているものとします。 また、簡単のためコンポーネントは分割せずに1つのコンポーネント内で完結するようにしています。
まずは基本形です。Line や Bar といったコンポーネントに対し、data と options(必要であれば) を渡します。
import React, { Component } from 'react'; import { Line } from 'react-chartjs-2'; class SampleChart extends Component { render { const data = { labels: ['April', 'May', 'June', 'July', 'August', 'September'], datasets: [ { data: [67, 79, 52, 41, 66, 43], // 省略 }, ], }; const options = { // 省略 }; return ( <Line data={data} options={options} /> ); } }
以下のようなグラフが表示されます。
使用できるコンポーネントの種類は react-chartjs-2 のレポジトリを、data
と options
の形式については、本家 chart.js のドキュメントを参照してください。
データの取得とグラフの更新
data
や labels
を動的に取得したい場面のほうが多いかと思うので、それらを state
として管理します。
実際の利用シーンとして、とあるグラフが日付を起点としてデータを取得しているとき、その起点となる日付を指定してグラフを更新したい、といった状況を想定してみます。
まず、ページの表示時には componentDidMount()
内でデータを取得します。
何らかの方法で日付を更新したとして、その日付が state
であればコンポーネントが再描画されます。その直後に呼び出されるライフサイクルメソッドとして componentDidUpdate()
があり、ここでその日付に応じてデータを再取得します。
以下がその実装例です。DatePicker は、カレンダーから日付を選択するようなコンポーネントを想定しています。
import React, { Component, Fragment } from 'react'; import moment from 'moment'; class SampleChart extends Component { constructor(props) { super(props) this.state = { date: moment() }; } componentDidMount() { this.getData(); } componentDidUpdate(prevProps, prevState) { if (prevState.date !== this.state.date) { this.getData(); } } getData() { const { data, labels } = fetchData(this.state.date); //日付に基づいた何らかのデータ取得処理 this.setState({ data: data, labels: labels }); } render { // 省略 各種変数の定義等 return ( <Fragment> <DatePicker date={date} onDateChange={ (newDate) => { return this.setState({ date: newDate }); }} /> //何らかの日付変更処理 <Line data={chartData} options={chartOptions} /> </Fragment> ); } }
if (prevState.date !== this.state.date) { ... }
の部分で更新前の日付と更新後の日付を比較していて、異なっていればデータが再取得されます。
クリックイベントの追加
グラフ要素をクリックして、クリックされたラベル(日付など)に応じて処理をしたいときのために、クリックイベントを追加することができます。
以下は、クリックしたグラフ要素に対応するラベルのインデックスをコンソールに出力するサンプルです。インデックスは elements[0]._index
で取得することができます。
import React, { Component } from 'react'; import { Bar } from 'react-chartjs-2'; class SampleChart extends Component { handleClick(elements) { if (elements.length === 0) return; console.log(elements[0]._index); } render { return ( <Bar data={data} options={options} onElementsClick={(elements) => this.handleClick(elements)} /> ); } }
拡張機能の利用
Chart.js はそれだけでもなかなか表現の自由度が高いものですが、さらにその幅を広げるための拡張機能(extensions)が用意されています。 extensions を用いると追加のグラフパターンが使えるようになったり、より凝った表示オプションを設定できるようになります。今回はその中の chartjs-plugin-datalabels を紹介します。 chartjs-plugin-datalabels はその名の通りラベルに関する拡張で、どのような種類のグラフに対しても自由な位置にラベルを表示できるようになります。
数値差が大きくなると小さい方の数値が把握しにくくなるので、パッと見てわかるようにしたいです。このプラグインを使って棒グラフの終端に数字を表示してみたいと思います。
ラベルの表示に関するパラメータはいろいろありますが、今回の実装のためには anchor
、align
が関係してきます。
具体的には、anchor でグラフの先頭、中心、終端のどこにラベルを置くかの基準点を指定し、align で anchor で指定した基準点からどの方向にラベルを設置するかを指定します。
これらを組み合わせて、anchor: 'end', align: 'right'
とすることで、終端の右側に表示します。
実装は以下のようになります。
import 'chartjs-plugin-datalabels'; const chartOptions = { plugins: { datalabels: { display: true, anchor: 'end', align: 'right', formatter(value) { if (value === null || value === 0) { return ''; } return `${value}%` }, }, layout: { padding: { right: 50, }, }, // 省略 };
ラベルを表示する余白をが必要がほしかったので右側に padding を入れています。
また、表示する値に単位を付ける、3桁ごとにカンマで区切るなどの表示形式は、formatter
の中で記述することができます。
今回は横向き棒グラフを使いたいので、HorizontalBar
コンポーネントを使います。
render ( <HorizontalBar data={chartData} options={chartOptions} /> )
これを実際に表示すると次のようになります。
まとめ
本記事では、react-chartjs-2 の使い方を、基礎から応用まで紹介しました。基本的な機能がデフォルトで揃っていながらも、非常に柔軟なライブラリでもあるので、グラフを実装する際はぜひカスタマイズして使ってみてください。
また、株式会社スタメンでは一緒に働く仲間を募集しています。お気軽にお話を聞きに来ていただければと思っています! 名古屋から世界へ!HRtechサービスの自社開発エンジニアと話しませんか?