iMind Developers Blog

iMind開発者ブログ

chart.jsでグラフ上に任意の画像を表示する

概要

chart.jsのグラフの上に任意の部分に画像を表示したかった。

バージョン情報

  • chart.js 2.8.0

動作確認ブラウザ

  • Firefox 67.0
  • Chromium 75.0

作成する画面

みんな大嫌いなPie Chartで中央に黒い太陽の絵を置いてみる。下記のようなイメージ。

f:id:mwsoft:20190622110132p:plain

ただのPie Chartの表示

まずはなるべくシンプルな円グラフを表示してみる。

<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css"/>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js"></script>
</head>

<body>
<div>
    <canvas id="myChart"></canvas>
</div>

<script>
// 初期設定
let config = {
    type: 'pie',
    data: {
        labels: ["docomo", "au", "softbank", "other"],
        datasets: [{
            data: [39.9, 27.4, 22.3, 10.4],
            backgroundColor: [
                'rgb(255, 99, 132)',
                'rgb(255, 159, 64)',
                'rgb(240, 240, 240)',
                'rgb(54, 162, 235)'
            ]
        }],
    }
};

// チャートの生成
let ctx = document.getElementById('myChart').getContext('2d');
new Chart(ctx, config);

</script>

</body>
</html>

実行結果

f:id:mwsoft:20190622110010p:plain

これの真ん中に画像を入れてみる。

グラフに任意の画像を表示

afterDrawイベントの後にcanvasのcontextを取ってきてそこでdrawImageする。

<div>
  <canvas id="myChart" style="border: solid 1px; width: 500px; height: 500px"></canvas>
</div>

<script>
// afterDrawの後にImageを差し込む
let sun_image = new Image();
sun_image.src = 'sun.png';
let drawImagePlugin = {
    afterDraw: function (c) {
        let context = document.getElementById('myChart').getContext('2d');
        let xPos = (500 - 100) / 2;
        let yPos = (500 - 100) / 2 + 20;
        context.drawImage(sun_image, xPos, yPos, 100, 100);
    }
}
Chart.pluginService.register(drawImagePlugin);

// 初期設定
let config = {
    type: 'pie',
    data: {
        labels: ["docomo", "au", "softbank", "other"],
        datasets: [{
            data: [39.9, 27.4, 22.3, 10.4],
            backgroundColor: [
                'rgb(255, 99, 132)',
                'rgb(255, 159, 64)',
                'rgb(240, 240, 240)',
                'rgb(54, 162, 235)'
            ]
        }],
    },
    options: {
        responsive: false
    }
};

// チャートの生成(イメージのload後に実行する)
sun_image.addEventListener("load", function() {
    let ctx = document.getElementById('myChart').getContext('2d');
    ctx.width = 500;
    ctx.height = 500;
    new Chart(ctx, config);
}, false);
</script>

これで動いた。

Imageのloadが終わる前にグラフ描画が走ると画像が消えてしまうことがあった為、チャートの生成をimageのload eventに入れてます。

responsiveだとwidth, heightが合わせづらいのでfalseにしてcanvasのサイズを500x500で固定してます。

中央に表示する際にX軸は (canvasのサイズ - 画像のサイズ) / 2 で中央になりますが、Y軸はlabelが上に書かれているので適当にずらしてます。

きっちり中央にするにはもっとchart.jsの中身を見ないとできないかもしれない(やらない)。

改定履歴

Author: Masato Watanabe, Date: 2019-06-22, 記事投稿