ウェブの画面にグラフを書きたい時に便利なJSライブラリChart.jsは、とても便利です。
単にチャートを書くだけでなく、チャートをクリックしたりマウスオーバーした際に、そのチャート上のデータを読み取る
ことができます。
マウスのクリックした時に、その時のカーソルの下にあるデータの取り方を紹介します。
サンプルコードはこちら。
マウスオーバーは簡単にできる。けど…
グラフ上の点をマウスオーバーした際の点に対応するデータを取るのは、options.tooltips.callback
を使うと簡単にできます。
例えば、マウスオーバーした時に表示されるツールチップのタイトルを現在時刻にするには、
下のように設定する。
new Chart(ctx,
type: 'scatter',
dataset: [{
data: [
{ x: 1, y: 2},
{ x: 2, y: 2},
{ x: 3, y: 3}
]
}],
options: {
tooltips: {
callbacks: {
title: function(tooltipItems, data) {
return new Date().toLocaleTimeString();
}
}
}
}
);
コールバック関数を設定できる種類やそれに渡される引数については、ドキュメントを参照してください。
しかし、これはあくまでもtooltipを描画するためのものであり、データを取るものではない。また、現在高まっている衝動は、クリックした時に対応したデータを取りたいという欲求である。
getElementAtEvent
を使おう
クリック時のイベントを元に、そのイベントが発生した場所にあるデータを返してくれるAPIがgetElementAtEvent
だ。
グラフを描画しているCanvas上のクリックイベントを拾うために、イベントハンドラを登録し、その内部で呼び出す。例えば、こんな感じ。
var myCanvas = document.getElementById('myCanvas');
var ctx = myCanvas.getContext('2d');
var myChart = new Chart(ctx, ...);
myCanvas.addEventListener('click', function(event) {
let item = myChart.getElementAtEvent(event);
if (item.length == 0) {
console.log('no element found.')
return;
}
item = item[0];
let data = item._chart.config.data.datasets[item._datasetIndex].data[item._index];
alert(`Clicked at (${data.x}, ${data.y})`);
});
getElementAtEvent
は、与えたイベントに対応するデータが無ければ空の配列を返します。ですので、データの存在の有無は、その配列の長さで判断できます。
ということで、インタラクティブなチャートを作れそうですね。
同一座標にある複数のデータを取得するには、
複数のデータを取得できるgetElementsAtEvent
を試してみたのですが、関係ないデータが取れてしまう問題に直面しました1。
それとは別に、イベントのハンドリングをhover
とonClick
またはonHover
で設定できます。
Chart
のコンストラクタに渡すoptions
に、以下のように渡します。
options: {
hover: {
mode: 'point'
},
onClick: function(event, elements) {
console.log(`Found ${elements.length} elements`);
elements.forEach(function(element) {
let point = myChart.data.datasets[element._datasetIndex].data[element._index];
console.log(point);
})
}
hover
は、一見hover時のみの挙動を決めるように見えますが、マウスイベントに対しての挙動を決める設定です。後に設定するcallback関数をどのイベントで呼び出すかは、別途、options.events
プロパティで設定します。デフォルトは全てのイベントで呼びだされます。
options.hover.mode
は、マウスカーソルを基準にどういった点を選択の対象にするかを設定するオプションです。デフォルト値のnearest
は最もカーソルに近い一点を選択します。今回は同一の座標点全てを取得したいので、point
を指定しています。他にもオプションがあるので、ドキュメントを参照ください。
今回はクリック時のマウスカーソル下にあるデータ点を取りたいので、onClick
を実装します。onClick
で指定した関数に渡される引数は、発生したイベントと、そこに関連するデータ点の配列の2つです。データ点の配列は、先のgetElementAtEvent
の返り値と同じChartElement
のオブジェクトの配列です。ChartElement
のオブジェクトは、何番目のdatasetのデータなのかを指す_datasetIndex
、さらにその中の何番目のデータ点なのかを表す_index
を持っているので、それらを用いて、マウスカーソル下のデータ点を取得できます。
参考
- Chart.js | Open source HTML5 Charts for your website
- Chart.js API · GitBook
- Tooltip · GitBook
- Events · GitBook
- Sample code for how to handle an event which a data point is clicked.
-
原因がまだわかっていませんが、とりあえずGitHubのChartjsのリポジトリにレポートしようと思います。 ↩