【JavaScript】chart.jsでフォントサイズをwidthに応じてレスポンシブにする方法

JavaScript

JavaScriptのchart.jsの使い方を紹介します。
とくにフォントサイズをwidthに応じてレスポンシブにする方法を紹介します。

Chart.jsの公式サイト

https://www.chartjs.org/
デモページ
ドキュメント

Chart.jsの始め方

cdnの場合:https://cdnjs.com/libraries/Chart.js
あとは、NPMやGitHubからChart.jsを取得できます。(上のドキュメント参照)

完成コード


document.addEventListener('DOMContentLoaded', () => {
  setChart();
});

/**
 * レーダーチャートをセットする関数
 * @return void
 */
function setChart() {
  const FRAMERATE = 60;
  const canvasParents = document.querySelectorAll('.jsCanvasParent');
  if (canvasParents) {
    canvasParents.forEach(canvasParent => {
      const canvas = canvasParent.querySelector('canvas');
      const ctx = canvas.getContext('2d');
      const config = getConfig(canvas);

      const myChart = new Chart(ctx, config);
    });
  }
}

/**
 * configを取得する関数
 * @param {object} - canvas
 * @return {object} - config
 */
function getConfig(canvas) {
  // ラベル
  const labels = [
    '年数', //age
    '安全性', //safety
    '快適性', //comfortability
    '利便性', //convenience
    '環境', //environment
    'おすすめ度', //recommend
  ];
  // データ
  const canvasData = canvas.dataset;
  const data = {
    labels,
    datasets: [
      {
        data: [
          canvasData.age,
          canvasData.safety,
          canvasData.comfortability,
          canvasData.convenience,
          canvasData.environment,
          canvasData.recommend,
        ],
        backgroundColor: 'rgba(0, 95, 122, 0.2)',
        borderColor: 'transparent',
        pointRadius: 0,
        // label: 'name', // chartの名前
        // pointStyle: 'circle',
        // pointBorderColor: "#fff",
        // pointBackgroundColor: "rgba(179,181,198,1)",
      },
    ],
  };

  // 見た目の設定
  const config = {
    type: 'radar',
    data: data,
    options: {
      responsive: true,
      // maintainAspectRatio: true,
      //label非表示
      plugins: {
        legend: {
          display: false,
        },
      },
      scale: {
        max: 5, //最大値
        min: 0, //最小値
        stepSize: 1, //区切り値
      },
      scales: {
        r: {
          backgroundColor: 'white', // 背景色
          // グリッドライン
          grid: {
            color: '#231815',
            lineWidth: 0.5,
          },
          // アングルライン
          angleLines: {
            color: '#231815',
            lineWidth: 0.5,
          },
          // ポイントラベル
          pointLabels: {
            color: 'black',
            // font: {
            //   size: 10,
            //   weight: 'bold',
            // },
            font: function (context) {
              var width = context.chart.width;
              // var size = Math.round(width / 25);
              var size = Math.round(width / 28);
              return {
                size: size,
                weight: 600,
              };
            },
            // backdropColor: 'unset',
            // backdropPadding: 5,
            // padding: 20,
          },
        },
      },
    },
  };
  return config;
}

イベントを設定


document.addEventListener('DOMContentLoaded', () => {
  setChart();
});

まずはレーダーチャートをセットする関数setChart()をセットしたいタイミングで発火させます。

レーダーチャートをセットする関数


/**
 * レーダーチャートをセットする関数
 * @return void
 */
function setChart() {
  const FRAMERATE = 60;
  const canvasParents = document.querySelectorAll('.jsCanvasParent');
  if (canvasParents) {
    canvasParents.forEach(canvasParent => {
      const canvas = canvasParent.querySelector('canvas');
      const ctx = canvas.getContext('2d');
      const config = getConfig(canvas);

      const myChart = new Chart(ctx, config);
    });
  }
}

FRAMERATEを設定することで、無駄に描画をやりすぎてパフォーマンスを下げることのないようにします。
パフォーマンスに関しては、他にもアニメーションをやめたりできるので、ドキュメントのパフォーマンスを参照してみてください。

上の場合、jsCanvasParentクラスがついているものを取得し、その子要素のcanvas要素を取得します。
canvas.getContext('2d')というのは、2Dグラフィックを描画するためのメソッドやプロパティをもつオブジェクトを返すものです。
これで2Dのメソッドやプロパティをいろいろ使えるようになります。

チャートを描くための設定(config)は長くなるので、別の関数getConfig()に切り分けています。

そして、Chartをインスタンス化します。
その際、第一引数には、canvas要素のgetContext('2d’)を格納した変数を渡します。
第二引数には、チャートを描くための設定(config)を格納した変数を渡します。

configを取得する関数

configを取得する関数の大枠


  /**
 * configを取得する関数
 * @param {object} - canvas
 * @return {object} - config
 */
function getConfig(canvas) {
  // ラベル
  const labels = [

  ];
  // データ
  const canvasData = canvas.dataset;
  const data = {
    labels,
    datasets: [
    ],
  };

  // 見た目の設定
  const config = {

  };
  return config;
}

まず、getConfig()というconfigを取得する関数を作成します。
長くなるので、まずは大枠を説明します。
チャートとなるラベル、データをそれぞれ用意して、それをconfigオブジェクトに格納して、そのconfigオブジェクトreturnして返す関数を作成します。

チャートのラベルになる部分を配列にします。
描画するデータは、どこかからデータを取得して、dataオブジェクトに代入します。上の場合、以下のようにcanvasにデータ属性をセットしてその値を取得しています。

canvasにデータ属性をセットする


<div class="jsCanvasParent">
  <canvas
    data-age="4"
    data-safety="5"
    data-comfortability="3"
    data-convenience="5"
    data-environment="5"
    data-recommend="5"
  ></canvas>
</div>

上のようにして、サーバーサイドからデータをセットすれば動的に表示できます。

ラベルの設定


  /**
 * configを取得する関数
 * @param {object} - canvas
 * @return {object} - config
 */
function getConfig(canvas) {
  // ラベル
  const labels = [
    '- 築年数 -', //age
    '- 安全性 -', //safety
    '- 快適性 -', //comfortability
    '- 利便性 -', //convenience
    '- 住環境 -', //environment
    '- おすすめ度 -', //recommend
  ];

  // 見た目の設定
  const config = {

  };
  return config;
}

チャートのラベルは簡単で、labelsなどの変数を用意して、配列でそれぞれの名前を格納します。ラベルも動的にしたい場合は、JavaScriptでどこかから取得します。
そして、configオブジェクトに格納して、それを返します。

データの設定


  /**
 * configを取得する関数
 * @param {object} - canvas
 * @return {object} - config
 */
function getConfig(canvas) {
  // ラベル
  const labels = [
    '- 築年数 -', //age
    '- 安全性 -', //safety
    '- 快適性 -', //comfortability
    '- 利便性 -', //convenience
    '- 住環境 -', //environment
    '- おすすめ度 -', //recommend
  ];
  // データ
  const canvasData = canvas.dataset;
  const data = {
    labels,
    datasets: [
      {
        data: [
          canvasData.age,
          canvasData.safety,
          canvasData.comfortability,
          canvasData.convenience,
          canvasData.environment,
          canvasData.recommend,
        ],
        backgroundColor: 'rgba(0, 95, 122, 0.2)',
        borderColor: 'transparent',
        pointRadius: 0,
        // label: 'name', // chartの名前
        // pointStyle: 'circle',
        // pointBorderColor: "#fff",
        // pointBackgroundColor: "rgba(179,181,198,1)",
      },
    ],
  };

  // 見た目の設定
  const config = {

  };
  return config;
}

先程作成したラベルの変数をdataに格納します。datasets配列に、オブジェクトとして、データを格納します。
格納するデータは、上の場合、canvas要素のデータ属性に指定されたそれぞれの値です。
背景などの変更があったり、チャート名などを記載したい場合は、ここで設定します。

見た目の設定


    // 見た目の設定
    const config = {
    type: 'radar',
    data: data,
    options: {
      responsive: true,
      // maintainAspectRatio: true,
      //label非表示
      plugins: {
        legend: {
          display: false,
        },
      },
      scale: {
        max: 5, //最大値
        min: 0, //最小値
        stepSize: 1, //区切り値
      },
      scales: {
        r: {
          backgroundColor: 'white', // 背景色
          // グリッドライン
          grid: {
            color: '#231815',
            lineWidth: 0.5,
          },
          // アングルライン
          angleLines: {
            color: '#231815',
            lineWidth: 0.5,
          },
          // ポイントラベル
          pointLabels: {
            color: 'black',
            // font: {
            //   size: 10,
            //   weight: 'bold',
            // },
            font: function (context) {
              var width = context.chart.width;
              // var size = Math.round(width / 25);
              var size = Math.round(width / 28);
              return {
                size: size,
                weight: 600,
              };
            },
            // backdropColor: 'unset',
            // backdropPadding: 5,
            // padding: 20,
          },
        },
      },
    },
  };

上で作成したdataオブジェクトをconfigのdataに格納することですべて紐づくことになります。

typeでチャートの種類を指定

typeでチャートの種類を指定します。

レスポンシブにしたい場合

重要な設定としては、レスポンシブにしたい場合、responsive: trueにします。

レジェント不要な場合

レジェントが不要な場合、pluginsのlegendをdisplay: falseに設定します。

スケールをカスタマイズする

scaleで、最大値、最小値、数値の区切りなどを設定できます。

より細かい設定をしたい場合

scalesでグリッド線やアングルラインなどの色を変更したり、ポイントラベルも変更できます。

フォントサイズをwidthに応じてレスポンシブにしたい

フォントサイズもscalesで指定できます。


font: {
  size: 10,
  weight: 'bold',
},

上のようにしてしますと、10pxで固定になります。
そのため、レスポンシブにするための関数を作成します。


font: function (context) {
  var width = context.chart.width;
  // var size = Math.round(width / 25);
  var size = Math.round(width / 28);
  return {
    size: size,
    weight: 600,
  };
},

上の場合、チャートのwidthに応じて、フォントサイズを可変させるという関数になります。
これで、フォントサイズをwidthに応じてレスポンシブにすることができます。

チャートをレスポンシブにする際のCSSの注意点

チャートをレスポンシブにする場合、canvas要素にcssを適用させるのではなく、その親要素をcssで制御します。
親要素を可変にすれば、上で紹介した、responsive: trueになっていれば、canvas自体も可変させることができます。