Chart.js 2 の散布図でツールチップを変更する方法

はじめに

一昨日の「Chart.js 2 で散布図(Scatter plot)を実装する方法」では Chart.js で散布図を作る方法や軸ラベルなどの設定方法をご紹介しました。

ところで Chart.js では、散布図のマーカー上にマウスカーソールを合わせると吹き出しが出現し、x と y の値が (x, y) の形で表示されます。

これはツールチップと呼ばれるもので、他のグラフでも使える機能なのですが、Chart.js ではオプション設定でその内容やスタイルを変更することができます。

今日は Chart.js 2 の散布図でツールチップを変更する方法をご紹介します。

前回同様、今回も Chart.js 2.9.3 を使いました。

目次
  1. 下準備
  2. ツールチップの変更
  3. おわりに

1. 下準備

今回使用した HTML と js です。どちらも一昨日に紹介したコードをベースにしていますので、詳しくはそちらをご参照ください。

/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>散布図(Scatter plot)</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
  <script>
    // データ
    var plotData = {
      group1: [
        { x: 1,  y:  81}, { x: 1,  y: 124}, { x: 2,  y: 130},
        { x: 2,  y: 101}, { x: 3,  y: 137}, { x: 3,  y: 132},
        { x: 3,  y: 152}, { x: 4,  y: 137}, { x: 5,  y: 134},
        { x: 5,  y: 142}, { x: 6,  y: 149}, { x: 7,  y: 152},
        { x: 8,  y: 158}, { x: 9,  y: 155}, { x: 10, y: 166},
      ],
      group2: [
        { x: 1,  y:  41}, { x: 1,  y: 121}, { x: 1,  y: 100},
        { x: 2,  y:  96}, { x: 3,  y: 113}, { x: 4,  y:  89},
        { x: 5,  y: 124}, { x: 5,  y: 137}, { x: 5,  y: 151},
        { x: 6,  y: 161}, { x: 6,  y: 130}, { x: 7,  y: 126},
        { x: 7,  y: 122}, { x: 9,  y: 149}, { x: 10, y: 205},
      ]
    }
  </script>
  <script src="js/app.js"></script>
</head>
<body>
  <canvas id="chart-area" width="640" height="320"></canvas>
</body>
</html>
/js/app.js
window.onload = function () {
  var data = {
    datasets: [
      {
        label: 'Group1',
        data: plotData.group1,
        backgroundColor: 'rgba(0, 159, 255, 0.45)',
        borderColor: 'rgba(0, 159, 255, 0.5)',
      },
      {
        label: 'Group2',
        data: plotData.group2,
        backgroundColor: 'rgba(255, 48, 32, 0.45)',
        borderColor: 'rgba(255, 48, 32, 0.5)',
      },
    ],
  };

  var options = {
    responsive: false,
    legend: {
      align: 'start',
      position: 'right',
      labels: { padding: 15 }
    },
    scales: {
      xAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'プレイ回数',
        },
        ticks: { min: 0 },
      }],
      yAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'スコア(点)',
        },
        ticks: { min: 0 }
      }]
    },
  };

  var ctx = document.getElementById('chart-area').getContext('2d');
  new Chart(ctx, {
    type: 'scatter',
    data: data,
    options: options,
  });
}

2. ツールチップの変更

ツールチップの設定は options.tooltips で行います。
app.js に下記のように追記してください。

ビギナーの方向けに、コメントを多めにつけています。

/js/app.js
window.onload = function () {
  var data = {
    ...
  };

  var options = {
    ...
  };

  // ▼ これを追加
  options.tooltips = {
    // 吹き出しの背景色
    backgroundColor: "rgba(19, 56, 95, 0.9)",
    // 吹き出し内の余白
    xPadding: 12,
    yPadding: 10,
    // マーカーによって変更するもの
    callbacks: {
      // ツールチップの表示内容
      label: function(tooltipItem, data) {
        // グループ名
        var groupName = data.datasets[tooltipItem.datasetIndex].label;
        // X 軸ラベル
        var xAxesLabel = options.scales.xAxes[0].scaleLabel.labelString;
        // y 軸ラベル
        var yAxesLabel = options.scales.yAxes[0].scaleLabel.labelString;

        // 表示するテキスト
        // x の値が tooltipItem.label
        // y の値が tooltipItem.value
        return ` ${groupName} | ${xAxesLabel}: ${tooltipItem.label} | ${yAxesLabel}: ${tooltipItem.value}`;
      }
    }
  };

  var ctx = ...
}

これを実行すると、ツールチップが下記のようになります。

options.tooltips で設定できる項目は下記ページで確認できます。

項目が多いので、翻訳されているサイトも併せてご紹介します。内容の整合性は確認していませんので、同項目を公式サイトでも確認して頂けるといいかなと思います。

callbacks の部分については、同ページ内の「Label Callback」にあるサンプルコードを手がかりに、console.log() を使って、引数の tooltipItem と data の中身を調べながら実装しました。

表示する文字列は自由に変更できますが 「¥n」で改行はできないのでご注意ください。

3. おわりに

ツールチップのカスタムも簡単で便利ですね。

サンプルコードでは、引数の tooltipItem と data の情報を使う例を書きたくて、グループや軸名をそのまま表示していますが、個人的にはもうちょっとスッキリさせた方がいいかなと思っています。

なお chart.js にはツールチップをより柔軟に変更できるように External Custom Tooltips という機能が用意されています。この機能を使えばツールチップを HTML で出力することができるようです。

僕はまだ使ったことがないのですが、下記公式ドキュメントにサンプルコードが紹介されていますので、気になる方はご参照ください。