chart.jsでぐりぐり動くグラフを作る

こんな風にスライダーをぐりぐりと動かすとそれに応じて表示が変わるグラフをchart.jsを使って作っていく。

![chart_movie.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/28792/5156e89c-f66f-6e7c-887a-22bef7e0f395.gif)

ここでは$f(x)=ax^2+bx+c$という関数をプロットすることにする。パラメータとして$a$,$b$,$c$の３つがあるが、それらをスライダーでぐりぐりと動かす。

[デモはこちら](https://jsfiddle.net/jnLp58kw/)

# chart.jsとは？

ここではグラフの描画に[chart.js](https://www.chartjs.org/)を使う。 chart.jsとはグラフをブラウザ上で表示するためのJSのライブラリの一つ。
グラフを作るためのライブラリといえばd3.jsが有名だが、より簡単にグラフを書くことに特化したライブラリ。プロットを作るだけなら本当に簡単に書くことができる。

[chart.js入門](https://qiita.com/kazu56/items/17acf7ad2d87d6b28173) の記事が参考になる。
またオフィシャルページの[サンプル集](http://www.chartjs.org/samples/latest/)を見れば、だいたいどんなグラフを作ることができるかわかる。

# 作成方法

まずはhtmlにスライダーを入れる。

```html
    <div class="slidecontainer" id="sliders">
      <input type="range" min="-1" max="1" value="0" step="0.1" class="slider" id="slider_a">a : <span id="val_a">0</span><br/>
      <input type="range" min="-1" max="1" value="0" step="0.1" class="slider" id="slider_b">b : <span id="val_b">0</span><br />
      <input type="range" min="-1" max="1" value="0" step="0.1" class="slider" id="slider_c">c : <span id="val_c">0</span><br />
    </div>
```

このようにして[-1,1]の範囲で動かせるようにした。

続いて、chart.jsで描画する領域のcanvasタグを作る。divタグはchartのサイズを指定するためのもの。

```html
    <div class="chart-container" style="position: relative; height:40vh; width:80vw">
      <canvas id="myChart"></canvas>
    </div>
```

chart.jsライブラリをCDN経由で取得

```html
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script>
```

以上でHTML側の準備は完了。

続いて、JSの中でプロットする点のx座標とy座標を計算

```js
const xs = [];
for(let i=-20; i<21; i++) { xs.push(i*0.1); }    // xs = [-2.0, -1.9, -1.8, .... 2.0]  x:-2~2の範囲でプロットする
function calc_ys(xs,a,b,c) {             // yの座標を計算するための関数
  return xs.map(x => a*x*x+b*x+c);
}
```

つづいてChartオブジェクトを作成しグラフを描画する。

```js
const ctx = document.getElementById("myChart").getContext('2d');
let myChart = new Chart(ctx, {
  type: 'line',
  data: {
    labels: xs,            // x座標の配列
    datasets: [{
      label: 'ax^2 + bx + c',
      data: calc_ys(xs,0,0,0)     // y座標の配列（初期化するときには、a=b=c=0と仮にしている）
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          min:-4, max:4           // yについて[-4,4]の範囲で描画するように固定。これがないと、データの値に応じて表示領域が変わってしまう。
        }
      }]
    }
  }
});
```

これでグラフが描画するところまでできる。あとは、スライダーの値に応じて変更する箇所を実装する。
y座標は `myChart.data.datasets[0].data` に格納されているので、この配列を新しいものに置き換える。その後`myChart.update()`を呼ぶとグラフが更新される。

```js
var sliders = document.getElementById("sliders");
sliders.addEventListener("input", function() {
  let a = document.getElementById("slider_a").value;     // sliderの値を取得
  let b = document.getElementById("slider_b").value;
  let c = document.getElementById("slider_c").value;
  document.getElementById("val_a").textContent = a;      // 取得した値を"#val_a"のテキストに表示
  document.getElementById("val_b").textContent = b;
  document.getElementById("val_c").textContent = c;
  myChart.data.datasets[0].data = calc_ys(xs,Number(a),Number(b),Number(c));  // プロットのy座標のデータを新しいもので置き換える。
  myChart.update();                                      // 新しいデータを反映させる
}, false);
```

以上でぐりぐり動くプロットが実装できる。

全体のソースコードは[こちら](https://jsfiddle.net/jnLp58kw/) を参照してほしい。