はじめに
ダッシュボードを作るとき、グラフの実装って地味に面倒なんですよね。Chart.jsで済む場合もあるけど、もう少し凝ったことをしたいとか、大量データを扱いたいときに物足りなさを感じることがあります。
そこで今回紹介するのがApache ECharts。GitHubスター数6万5千超え、月間600万ダウンロードという実績を持つ、Apacheプロジェクトのデータビジュアライゼーションライブラリです。
個人的には、「とりあえずこれ入れとけば大抵のグラフは作れる」という安心感があるライブラリだと思っています。
とはいえ、説明を読むより実際に触ってみる方が早いと思います。売上データを書き換えたり、棒グラフと折れ線グラフを切り替えたりをブラウザ上でそのまま試せるサンプルを用意したので、先に動きを見たい方はこちらからどうぞ。
特徴・メリット
20種類以上のチャートタイプ
棒グラフ、折れ線、円グラフといった基本はもちろん、ヒートマップ、サンバースト、ツリーマップ、さらには3Dチャートまで対応しています。12種類のコンポーネントと組み合わせることで、かなり複雑な可視化も実現できます。
大量データ処理に強い
これが一番の推しポイントなんですが、1000万件のデータをリアルタイムで描画できます。プログレッシブレンダリングとストリーム読み込みに対応しているので、大規模なデータセットでもブラウザが固まることなく表示できます。
業務システムで「過去5年分のデータを一括表示したい」みたいな要件が来ても、EChartsなら対応できる可能性が高いです。
Canvas/SVG両対応
レンダリングエンジンをCanvasとSVGで切り替えられます。大量データならCanvas、印刷品質が必要ならSVGという使い分けができるのは便利ですね。
宣言的なAPI設計
オプションオブジェクトを渡すだけでグラフが描ける宣言的な設計になっています。JSONで設定を管理できるので、サーバーからグラフ設定を取得して動的に描画するようなケースにも向いています。
アクセシビリティ対応
最近のライブラリらしく、スクリーンリーダー向けの説明文を自動生成してくれます。アクセシビリティ要件がある案件でも安心して使えます。
インストール方法
npm経由(推奨)
npm install echarts --save
CDN経由
手軽に試したいならCDNでも使えます。
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
バンドルサイズについて
フル版だと383KB(minified + gzipped)とそこそこのサイズになります。必要なモジュールだけインポートする方法もあるので、本番環境ではそちらを検討した方がいいかもしれません。
EChartsのサンプルを動かす
EChartsの基本は、echarts.init()でコンテナ要素をチャートインスタンス化し、setOption()にオプションオブジェクトを渡すだけです。まずは月別売上データを棒グラフにした最小構成を見てみましょう。
import * as echarts from 'echarts'
const chart = echarts.init(document.getElementById('chart'))
chart.setOption({
tooltip: {},
xAxis: { data: ['1月', '2月', '3月', '4月', '5月', '6月'] },
yAxis: {},
series: [{ type: 'bar', data: [120, 200, 150, 80, 70, 110] }]
})
下のサンプルはこれを実際に動かせる形にしたものです。入力欄のカンマ区切り数値を書き換えると、inputイベントのたびにsetOption()が呼び直されてグラフがその場で更新されます。試しに数値を1つ減らしたり、300のような大きい値を混ぜたりしてみてください。
入力欄を空にすると系列データが空配列になり、棒グラフが消えるのが確認できると思います。逆に数値をカンマ区切りで足していくと、その数だけxAxisのラベルも自動生成されて棒が増えます。EChartsはsetOption()を呼び直すたびに差分を反映してくれるので、フォーム入力やAPIレスポンスに応じてグラフを更新するUIとの相性が良いことが分かるかと思います。
基本的な使い方
シンプルな棒グラフ
import * as echarts from 'echarts';
// コンテナ要素を取得してインスタンス化
const chart = echarts.init(document.getElementById('chart'));
// オプションを設定
const option = {
title: {
text: '月別売上'
},
tooltip: {},
xAxis: {
data: ['1月', '2月', '3月', '4月', '5月', '6月']
},
yAxis: {},
series: [
{
name: '売上',
type: 'bar',
data: [120, 200, 150, 80, 70, 110]
}
]
};
// 描画
chart.setOption(option);
これだけでツールチップ付きの棒グラフが完成します。正直、この手軽さはかなり魅力的です。
複合グラフ
折れ線と棒グラフを組み合わせるのも簡単です。
const option = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['売上', '前年比']
},
xAxis: {
data: ['1月', '2月', '3月', '4月', '5月', '6月']
},
yAxis: [
{ type: 'value', name: '売上(万円)' },
{ type: 'value', name: '前年比(%)' }
],
series: [
{
name: '売上',
type: 'bar',
data: [120, 200, 150, 80, 70, 110]
},
{
name: '前年比',
type: 'line',
yAxisIndex: 1,
data: [105, 120, 98, 85, 90, 115]
}
]
};
レスポンシブ対応
ウィンドウリサイズへの対応も簡単です。
window.addEventListener('resize', () => {
chart.resize();
});
実践的なユースケース
ダッシュボード構築
管理画面のダッシュボードは、EChartsの最も一般的な使い道ですね。売上推移、ユーザー数の変動、カテゴリ別の構成比など、複数のグラフを並べて表示するケースに向いています。
データ連携の方法としては、REST APIからJSONでデータを取得してsetOptionで更新するパターンが多いと思います。ダッシュボードでは同じデータを棒グラフと折れ線グラフで見比べたい、という場面もよくあるので、ボタンで表示形式を切り替えるパターンを見てみましょう。ポイントは、seriesのtypeプロパティだけを含むオブジェクトをsetOption()に渡すと、他の設定を保ったまま該当箇所だけ差分更新されることです。
const option = {
xAxis: { data: ['1月', '2月', '3月', '4月', '5月', '6月'] },
yAxis: {},
series: [{ name: '売上', type: 'bar', data: [120, 200, 150, 80, 70, 110] }]
}
chart.setOption(option)
// seriesのtypeだけ渡せば、そこだけ差分マージされて切り替わる
function switchType(type) {
chart.setOption({ series: [{ type }] })
}
switchType('line') // 折れ線グラフに切り替わる
実際にボタンで切り替えられるようにしたのが下のサンプルです。「棒グラフ」「折れ線グラフ」ボタンを押すと、同じデータのまま表示形式だけが変わります。
このようにsetOption()は渡した部分だけをマージしてくれるので、ダッシュボードで複数のKPIカードごとに「表示形式切り替えボタン」を付けるような実装も、同じ考え方で作れます。
リアルタイムモニタリング
WebSocketと組み合わせて、サーバーのメトリクスやIoTセンサーのデータをリアルタイム表示するような使い方もできます。appendDataメソッドを使えば、既存のデータに追加する形で効率的に更新できますが、直近N件だけをスライドウィンドウ表示したい場合は、配列を作り直してsetOption()で丸ごと渡し直す方法でも十分実用的です。
let data = [10, 12, 8, 15, 9, 11]
function tick() {
// 先頭を1つ捨てて末尾に新しい値を追加(スライドウィンドウ)
data = [...data.slice(1), Math.round(Math.random() * 25)]
chart.setOption({
xAxis: { data: data.map((_, i) => `t-${data.length - i}`) },
series: [{ data }]
})
}
setInterval(tick, 800)
下のサンプルは「開始」ボタンを押すと0.8秒ごとに疑似センサー値を1件追加し、グラフが流れるように更新される様子を確認できます。
「停止」ボタンでclearIntervalが呼ばれるまで更新が続くので、実運用でWebSocketのメッセージ受信時に同じrender()相当の処理を呼ぶ形に置き換えれば、そのままリアルタイムダッシュボードに応用できます。
ツールチップのカスタマイズ
EChartsのtooltip.formatterにはコールバック関数を渡せるので、デフォルトの数値表示だけでなく、前年比や単位付きの補足情報をホバー時に出すこともよくある使い方です。
chart.setOption({
tooltip: {
trigger: 'axis',
formatter: (params) => {
const p = params[0]
return `${p.axisValue}<br/>売上: ${p.data}万円<br/>前年比目安: ${(p.data / 100).toFixed(1)}倍`
}
}
})
チェックボックスでデフォルトのツールチップとカスタムフォーマッターを切り替えられるようにしたのが下のサンプルです。棒グラフにマウスを乗せたときの表示内容の違いを比べてみてください。
チェックを外すとデフォルトのシンプルな数値表示に戻り、入れるとformatterで組み立てたHTML文字列が表示されます。setOption()の第2引数にtrue(notMerge)を渡しているのは、formatterをなしに戻したいときにマージだと古い設定が残ってしまうためです。
地図可視化
ECharts GLを使えば、地図上にデータをプロットすることも可能です。店舗の売上を地図上にヒートマップ表示するとか、配送ルートを可視化するとか、そういった用途にも対応できます。
React/Vueで使う場合
素のJavaScriptでも使えますが、フレームワークと組み合わせる場合は公式のラッパーライブラリを使うと楽です。
React
npm install echarts-for-react
import ReactECharts from 'echarts-for-react';
function Chart() {
const option = {
xAxis: { data: ['A', 'B', 'C'] },
yAxis: {},
series: [{ type: 'bar', data: [10, 20, 30] }]
};
return <ReactECharts option={option} />;
}
Vue
npm install vue-echarts
コンポーネントとして使えるようになるので、Vueのリアクティブシステムと自然に統合できます。
まとめ
EChartsは「とりあえずこれ入れておけば間違いない」系のチャートライブラリです。
- 20種類以上のチャートタイプ
- 1000万件のデータ処理能力
- 宣言的で扱いやすいAPI
- 13年の開発実績とApacheプロジェクトの信頼性
Chart.jsより高機能なものが必要、D3.jsほど低レベルな制御は不要、という中間的なニーズにピッタリはまります。
ダッシュボード開発やデータ可視化案件で「何使おう」と迷ったら、まずEChartsを検討してみてください。公式サイトのサンプルを眺めるだけでも、何ができるかイメージが湧くと思います。
公式サイト: https://echarts.apache.org/ GitHub: https://github.com/apache/echarts