Chart.js v2でのクリックイベントの扱い方


# 要約
1. v1ではグラフ毎にイベントからデータへ変換するメソッドが異なる
2. v2では、すべてのグラフで`getElementAtEvent`か`getElementsAtEvent`に統一された

# 背景
[Chart.js](http://www.chartjs.org/)はv2で大きな変更があります。
公式なmigration支援ドキュメントはありません。
[Issue](https://github.com/chartjs/Chart.js/issues/1925)はありますが、あまり手が回っていないようです

グラフの作り方の変更点は[v1.0 からの変更点](http://qiita.com/UedaTakeyuki/items/9f38a16e756deecab4b2#v10-%E3%81%8B%E3%82%89%E3%81%AE%E5%A4%89%E6%9B%B4%E7%82%B9)を見てください。

グラフのイベント処理にも変更があります。
この記事ではイベント処理の変更点を整理します。

# Chart.jsでのクリックイベントの取り扱い

Chart.jsはCanvasを使ってグラフを描画します。
Canvasは、要素にイベントハンドラーを設定することはできません。
Chart.jsは、Canvasのイベントハンドラーのイベントオブジェクトをグラフの要素に変換するAPIを提供しています。

v1とv2では、変換APIが変わりました。

# Cahrt.js v1

## サンプルコード
```v1.html
<!doctype html>
<html>

<head>
    <title>Bar Chart</title>
    <script src="node_modules/chart.js/Chart.js"></script>
</head>

<body>
    <canvas id="canvas"></canvas>
    <script>
        const barChartData = {
            "labels": [
                "January",
                "February",
                "March",
                "April",
                "May",
                "June",
                "July"
            ],
            "datasets": [{
                "fillColor": "rgba(220,220,220,0.5)",
                "strokeColor": "rgba(220,220,220,0.8)",
                "highlightFill": "rgba(220,220,220,0.75)",
                "highlightStroke": "rgba(220,220,220,1)",
                "data": [
                    91,
                    77,
                    21,
                    60,
                    61,
                    59,
                    83
                ]
            }, {
                "fillColor": "rgba(151,187,205,0.5)",
                "strokeColor": "rgba(151,187,205,0.8)",
                "highlightFill": "rgba(151,187,205,0.75)",
                "highlightStroke": "rgba(151,187,205,1)",
                "data": [
                    8,
                    67,
                    96,
                    87,
                    77,
                    5,
                    7
                ]
            }]
        }

        const canvas = document.querySelector("#canvas")
        const ctx = canvas.getContext("2d")
        const chart = new Chart(ctx).Bar(barChartData)

        canvas.addEventListener('click', (e) => console.log(chart.getBarsAtEvent(e)))
    </script>
</body>

</html>
```

## 起動
```
npm init -y
npm install chart.js@1.1.1
```

`v1.html`をブラウザで開きます。

![スクリーンショット 2016-06-20 15.15.34.png](https://qiita-image-store.s3.amazonaws.com/0/15964/b5d3bfa4-72d8-9f4f-6a28-174b75023ec1.png "スクリーンショット 2016-06-20 15.15.34.png")

このようなグラフが表示されます。

## クリックイベントの扱い

v1では、棒グラフの場合、[getBarsAtEvent](https://github.com/chartjs/Chart.js/blob/v1.1.1/docs/02-Bar-Chart.md#getbarsatevent-event-)を使って、MouseEventからクリックしたデータ（正確にはクリックした時にtooltipを表示しているデータ）を取得します。

`getBarsAtEvent`メソッドを使うと、次のように`ChartElement`の配列に変換されます。

![スクリーンショット 2016-06-20 15.18.54.png](https://qiita-image-store.s3.amazonaws.com/0/15964/322214be-f189-c215-5477-0bc573772c1b.png "スクリーンショット 2016-06-20 15.18.54.png")

1つの`ChartElement`には次の情報が含まれます。

```
{
  "value": 83,
  "label": "July",
  "strokeColor": "rgba(220,220,220,1)",
  "fillColor": "rgba(220,220,220,0.75)",
  "highlightFill": "rgba(220,220,220,0.75)",
  "highlightStroke": "rgba(220,220,220,1)",
  "_saved": {
    "value": 83,
    "label": "July",
    "strokeColor": "rgba(220,220,220,0.8)",
    "fillColor": "rgba(220,220,220,0.5)",
    "highlightFill": "rgba(220,220,220,0.75)",
    "highlightStroke": "rgba(220,220,220,1)",
    "width": 13,
    "x": 268,
    "y": 87.04210613821667
  },
  "width": 13,
  "x": 268,
  "y": 35.13798272595014,
  "base": 87.04210613821667
}
```

`value`と`label`を使えば、クリックした要素を取得できそうです。


# Chart.js v2

## サンプルコード

```v2.html
<!doctype html>
<html>

<head>
    <title>Bar Chart</title>
    <script src="node_modules/chart.js/dist/Chart.bundle.js"></script>
</head>

<body>
    <canvas id="canvas"></canvas>
    <script>
        const barChartData = {
            "labels": [
                "January",
                "February",
                "March",
                "April",
                "May",
                "June",
                "July"
            ],
            "datasets": [{
                "label": "Dataset 1",
                "backgroundColor": "rgba(220,220,220,0.5)",
                "data": [
                    3, -27, -46,
                    56, -87, -82,
                    86
                ]
            }, {
                "label": "Dataset 2",
                "backgroundColor": "rgba(151,187,205,0.5)",
                "data": [-88, -78,
                    74, -32,
                    35,
                    29,
                    62
                ]
            }]
        }

        const canvas = document.querySelector("#canvas")
        const ctx = canvas.getContext("2d")
        const chart = new Chart(ctx, {
            type: 'bar',
            data: barChartData
        })

        canvas.addEventListener('click', (e) => console.log(chart.getElementsAtEvent(e)))
    </script>
</body>

</html>
```

## 起動
```
npm init -y
npm install chart.js@latest
```

`v2.html`をブラウザで開きます。

![スクリーンショット 2016-06-20 15.26.15.png](https://qiita-image-store.s3.amazonaws.com/0/15964/baf2b0e8-a7b7-6ea7-441e-b09058e8db3e.png "スクリーンショット 2016-06-20 15.26.15.png")

このようなグラフが表示されます。

## クリックイベントの扱い
v2では、[getElementsAtEvent](http://www.chartjs.org/docs/#advanced-usage-prototype-methods)を使って、MouseEventからクリックしたデータを取得します。

`getElementsAtEvent `メソッドを使うと、次のように`ChartElement`の配列に変換されます。

![スクリーンショット 2016-06-20 15.44.11.png](https://qiita-image-store.s3.amazonaws.com/0/15964/835e79ad-da72-ba8f-c6cf-187509ff5480.png "スクリーンショット 2016-06-20 15.44.11.png")

`ChartElement`に含まれる情報も変更されました。


```
{
  "_datasetIndex": 0,
  "_index": 6,
  "hidden": false,
  "_model": {
    "x": 989.6839904785156,
    "y": 67,
    "label": "July",
    "datasetLabel": "Dataset 1",
    "base": 279,
    "width": 54,
    "backgroundColor": "rgba(196, 196, 196, 0.5)",
    "borderSkipped": "bottom",
    "borderColor": "rgba(0, 0, 0, 0.1)",
    "borderWidth": 0
  },
  "_view": {
    "x": 989.6839904785156,
    "y": 67,
    "label": "July",
    "datasetLabel": "Dataset 1",
    "base": 279,
    "width": 54,
    "backgroundColor": "rgba(196, 196, 196, 0.5)",
    "borderSkipped": "bottom",
    "borderColor": "rgba(0, 0, 0, 0.1)",
    "borderWidth": 0
  },
  "_start": null
}
```

`label`は`_model`配下に移動しています。
また`value`はなくなりました。
代わりに`_datasetIndex`と`_index`があります。元データから取得可能です。

# 参考
- [Chart.jsの線グラフに選択機能をつける - Qiita](http://qiita.com/granciel/items/67d95b35acede9f274e8)
- [Chart.js v2.0 で時系列グラフの描画 - Qiita](http://qiita.com/UedaTakeyuki/items/9f38a16e756deecab4b2)