/

chart.jsで凡例をCSSでカスタマイズする

chart.jsで凡例をCSSでカスタマイズする

chart.jsで凡例を表示させるとグラフの上、グラフの左と指定でき、さらに表示位置もstart、endと指定することができるため通常はあまり困ることはありません。

ただし、「CSSでカスタマイズできたらいいのに」と思うことはしばしばあると思います。

そこで本記事では凡例を自由にカスタマイズできる方法を紹介したいと思います。

Chart.js v3.7.0 を使用しています。

凡例のカスタマイズ

まず先に完成形です。

See the Pen chart js default by s-Kuma (@kumatechlab) on CodePen.

グラフ内の左上に凡例が確認できると思います。

このような凡例を作成していきます。

HTML部分

<div clsss="graph">
  <div id="legend-container" class="canvas-legend"></div>
  <canvas id="chart-sample"></canvas>
</div>

凡例の表示用にdiv要素を作成しておきます。この要素をjavascript側から操作します。

canvasはグラフ本体の表示用です。

インスタンス生成部分

const myChart = new Chart(
  document.getElementById( 'chart-sample' ),
  {
    type: 'bar',
    data: {
      labels: [
        '1月',
        '2月',
        '3月',
        '4月',
        '5月',
        '6月'
      ],
      datasets: [
        {
          label: '売上',
          data: [
            10,
            50,
            100,
            120,
            150,
            200
          ],
          backgroundColor: '#E91E63'
        }
      ]
    },
    options: {
      plugins: {
        htmlLegend: {
            containerID: 'legend-container',
        },
        legend: {
          display: false
        },
      }
    },
    plugins: [
        htmlLegendPlugin,
    ],
  }
);

グラフの部分に関しては特に変わったことはしていません。

凡例の部分だけ取り上げてみます。

legend: {
   display: false
},

この記述でデフォルトの凡例が非表示になります。

htmlLegend: {
   containerID: 'legend-container',
},

この記述は後程作成するプラグインで取り扱うためのIDを指定しています。

そして、先ほど作成したHTMLの凡例部分のIDでもあります。

今回紹介する方法で複数グラフを表示する場合このidはそれぞれのグラフで別々の値を指定するようにしてください。

plugins: [
  htmlLegendPlugin,
],

これは「htmlLegendPlugin」を使用するという記述です。

次で作成します。

プラグイン部分

const getOrCreateLegendList = ( chart, id ) => {
    const legendContainer = document.getElementById( id );
    let listContainer = legendContainer.querySelector( 'ul' );

    if (!listContainer) {
      listContainer = document.createElement( 'ul' );
      listContainer.classList.add( 'canvas-legend__list' );

      legendContainer.appendChild(listContainer);
    }

    return listContainer;
};

const htmlLegendPlugin = {
    id: 'htmlLegend',
    afterUpdate( chart, args, options ) {
        const ul = getOrCreateLegendList( chart, options.containerID );

        // Remove old legend items
        while (ul.firstChild) {
            ul.firstChild.remove();
        }

        // Reuse the built-in legendItems generator
        const items = chart.options.plugins.legend.labels.generateLabels( chart );

        items.forEach(item => {
            const li = document.createElement('li');
            li.classList.add( 'canvas-legend__item' );

            // Color box
            const boxSpan = document.createElement('span');
            boxSpan.style.background = item.fillStyle;
            boxSpan.style.borderColor = item.strokeStyle;
            boxSpan.style.borderWidth = item.lineWidth + 'px';
            boxSpan.classList.add( 'canvas-legend__box' );

            // Text
            const textContainer = document.createElement('p');
            textContainer.style.color = item.fontColor;
            textContainer.classList.add( 'canvas-legend__label' );

            const text = document.createTextNode(item.text);
            textContainer.appendChild(text);

            li.appendChild(boxSpan);
            li.appendChild(textContainer);
            ul.appendChild(li);
        });
    }
};

全体の流れとしては以下のようになっています。

  • HTMLで作成した凡例用要素の取得
  • その中にul作成
  • chart.jsの凡例作成機能で凡例を取得
  • 作成したulの中に凡例をクラスを振って配置

chart.jsのインスタンス生成時のオプションで変更される動的部分はjavascriptで直接要素をスタイリングしています。固定部分はわざわざjavascriptで指定する必要はないので、クラス名を付与してCSSでスタイリングをしています。

動的な変更部分は「Legend Item Interface」のものであれば利用可能です。

まとめ

以上、chart.jsの凡例のカスタマイズでした。

chart.jsの公式の「HTML Legend」を参考に作成しています。


<