ChartJSでオリジナルチャート、作れるって知ってました?
Voicy Advent Calendar 9日目の投稿です。VoicyではAndroidエンジニアをしています。ぬまです。
最近はフロントエンド開発にて、チャート表示機能の開発を携わらせていただきました。
採用したChart.jsについてご紹介したいと思います。
ChartJSって何?
美しく洗練されたデザインのグラフをあっという間に作れちゃう無料のツールです。
さらに、自分だけのオリジナルチャートを作り上げることも可能です。
採用事例が多いことから信頼性も高いです。
新型コロナウイルスが世界中で猛威を振るっていた過去が久しいですが、その対策サイトを公開している東京都でも、ChartJSが使われています。
はじめに
ChartJSには様々なタイプのチャートがありますが、ここでは以下のグラフを元にカスタマイズ例を紹介します。
筆者の開発環境はAngularとTypeScriptを使用しています。
Angularラッパーのng2-chartsを使用しています。
- line
- bar
- doughnut
導入
Chart.jsのインストールや初期設定は基本的に公式ドキュメントを参考にしました。
環境
- typescript 4.8.4
- angular 15.2.9
- chart.js 4.4.0
プラグインの作り方
Chart.jsのプラグインはチャートのデフォルトの挙動やレイアウトをカスタマイズまたは変更する方法です。
必要なAPIを実装したオブジェクトを以下のようにchartに渡してやるだけです。
以下は凡例の下の余白を調整しています。
this.chartConfig = {
type: 'line',
plugins: this.legendMargin,
...
};
private legendMargin = {
id: 'legendMargin',
beforeInit(chart) {
const fitValue = chart.legend.fit;
chart.legend.fit = function fit() {
fitValue.bind(chart.legend)();
return (this.height += 20);
};
},
};
X軸のラベルを時刻として認識させる方法
タイムスケールは、X軸ラベルに時間や日付・年月を表示するために使用されます。
xAxesのtypeにtimeを指定します。
こうすることでtimeオプションの指定が可能です。
const days = ['2023-09-03', '2023-09-04', '2023-09-05', '2023-09-06'];
const xlabels: Date[] = days.map((value) => moment(value).toDate());
this.chartConfig = {
type: 'line',
data: {
labels: xlabels,
datasets: dataset,
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'month',
displayFormats: format,
...
特定の日時単位でX軸ラベルを表示したい場合time.unit設定オプションに文字列を渡します。
例えば、月別で表示したいとき'month'、複数年のデータ群の時は'year'を渡すとというふうにグラフに表すデータ群によってX軸のラベル単位を切り分けます。
フォーマットはdisplayFormatsで指定します。
const displayFormats = {
day: 'yyyy/MM/dd', // 日付のフォーマットを指定
week: 'yyyy/MM/dd', // 週のフォーマットを指定
month: 'yyyy/MM/dd', // 月のフォーマットを指定
quarter: 'yyyy/MM', // 四半期のフォーマットを指定
year: 'yyyy', // 年のフォーマットを指定
};
ツールチップのカスタマイズ
スタイル
ツールチップは、マウスポインタをグラフ上にホバーすると情報を表示するようなUIです。
ツールチップ内はhtmlをコーディングしてごっそりスタイルをカスタマイズできます。let chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
plugins: {
tooltip: {
enabled: false,
position: 'nearest',
external: this.externalTooltipHandler,
callbacks: {
label: function (context) {
// 表示する情報をここで操作しツールチップに表示する
let label =
context.chart.data.datasets[context.datasetIndex].label +
':' +
this.listenerDatas.find(
(data) =>
data.label === context.chart.data.datasets[context.datasetIndex].label,
).values[context.dataIndex];
return label;
}.bind(this), // tsのフィールド変数を使いたい時はthisをバインドする
...
});
ツールチップの配置
ツールチップの表示位置は標準で'nearest', 'average'がありますが、カスタマイズするにはdeclare moduleでモジュールを定義する必要があります。
declare module 'chart.js' {
interface TooltipPositionerMap {
myCustomPositioner: TooltipPositionerFunction<ChartType>;
}
}
...
Tooltip.positioners.myCustomPositioner = function (
elements,
eventPosition,
) {
if (elements.length === 0) {
return false;
}
const element = elements[0];
const x = eventPosition.x;
const y = element.element.y;
return { x, y };
};
Lineグラフでの間の塗りつぶし
ChartJSのLineチャートではfillオプションを使って線グラフと線グラフの間の領域を塗りつぶすことができます。
this.chartConfig = {
type: 'line',
data: {
datasets: [
{
label: 'graph01',
data: [420, 240, 530, 760, 900, 890, 790],
fill: '+1', // 下の線グラフまで塗りつぶす
backgroundColor: '#018DEC1A', // 塗りつぶしの色
borderColor: '#018DEC',
borderWidth: 2,
yAxisID: 'y01',
},
{
label: 'graph02',
data: [220, 160, 230, 360, 40, 90, 190],
backgroundColor: '#2CCBA61A',
fill: 'start',// X軸まで塗りつぶす
borderColor: '#2CCBA6',
borderWidth: 2,
yAxisID: 'y02',
},
});
Barグラフを横に倒す
Barグラフの初期状態は垂直です。Barグラフを水平に表示したい場合は、indexAxis='y'をオプションに指定すれば可能です。
this.chartConfig = {
type: 'bar',
data: {
labels: ['熱心なファンの割合'],
datasets: datasets,
},
options: {
layout: {
padding: {
left: 30,
right: 30,
},
},
indexAxis: 'y',
...
}
};
Youtubeのチュートリアルチャンネルは見ておきたい
このチャンネルで2007本ものユースケースが紹介されています。
まとめ
ChartJSは複雑なデータを分かりやすく視覚化する素晴らしいツールです。そのカスタマイズ性により、さまざまな視覚的表現が可能となります。今回紹介したカスタマイズは一例です。ぜひ自分のニーズに合わせて試してみてください。
参考リンク
Discussion