"BOKU"のITな日常

テクノロジー以外にも、日常には、面白そうな”イット”がつまってるんだな

Chart.jsで縦横同じサイズの散布図サンプルを描く/django+Chart.js

簡単にできると思ってたら、意外に情報がなくて苦労したので、備忘を兼ねて書いておきます。

f:id:arakan_no_boku:20200422010037p:plain

 

 やりたいこと

 

pythonのmatplotlibでグラフィックを描くように、ブラウザでやりたいと思いました。

arakan-pgm-ai.hatenablog.com

Chart.jsを使います。

何もしないと、canvasのデフォルト(幅300px、高さ150px)のバランスで以下のように横長になります。

f:id:arakan_no_boku:20200423002623p:plain

これでは、具合が悪いので、以下のように縦横サイズが同じ真四角の散布図を描く方法を探しました。

f:id:arakan_no_boku:20200422220124p:plain 

 

簡単だと思ったのですが

 

簡単だとなめていたら、ちょっとだけハマりました。

canvasのサイズ指定についてこちらで調べたのが発端です。

misc.0o0o.org

参考にした部分を引用すると。

キャンバスサイズ変更を、CANVAS要素から直接の検出することはできません。

キャンバスレンダリングサイズとディスプレイサイズを更新するために、Chart.jsでは親コンテナを使用します。

ただしこの方法では、コンテナが相対配置(position:relative)されていることと、チャートキャンバスのみを含むことが必要です。

これにより、コンテナサイズの相対値を設定することでレスポンシブ機能が実現できます。

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


プログラムでコンテナサイズを変更することでも、チャートサイズを変更することができます。

chart.canvas.parentNode.style.height = '128px';

これを見て、javascript内で「chart.canvas.parentNode.style.height 」および「width」に指定すればコントロールできると思ったのですが・・。

見事にエラーになりました(笑)。

Uncaught ReferenceError: chart is not defined

そこから、Canvasのサイズを縦横同サイズを指定する方法を見つけるのに1時間くらいかかりました(笑)。

 

ソースコードと解説

 

結果的にできるようになった方法です。

まずは、HTML部分の抜粋です。

<div class="mycanvas">
    <canvas id="myChart"></canvas>
</div>
<script type="text/javascript" src="{% static "js/scatter01.js" %}"></script>

mycanvasクラスはCSSで以下のように定義してます。 

.mycanvas
{
width:500px;
height:500px;
}

{% static "js/scatter01.js" %}という書き方は、djangoのテンプレートからコピーしてきたからなので、django以外の環境だと適切な相対パスに書き換えてください。

後述するJavaScriptを「scatter01.js」という名前で保存し、それを<script>で読み込んでいます。

canvasのID「MyChart」は、JavaScriptセレクタで指定するためのものです。

今度は、JavaScript部分(scatter01.js)です。

window.chartColors = {
    red: "#FF0000",
    blue: "#00FF00"
};

var color = Chart.helpers.color;
function generateData() {
    var data = [];
    for (var i = 0; i < 120; i++) {
        data.push({
            x: Math.floor( Math.random()*100 ),
            y: Math.floor( Math.random()*100 )
        });
    }
    return data;
}

var scatterChartData = {
    datasets: [{
        label: 'dummy dataset',
        borderColor: window.chartColors.red,
        backgroundColor: window.chartColors.red,
        pointRadius: 3,
        data: generateData()
    }]
};

window.onload = function() {
    var ctx = document.getElementById('myChart').getContext('2d');
    ctx.canvas.width=500;
    ctx.canvas.height=500;
    window.myScatter = Chart.Scatter(ctx, {
        data: scatterChartData,
        options: {
            title: {
                display: true,
                text: 'Chart.js Scatter Chart'
            },
            scales: {
                xAxes: [{
                    gridLines: {                       // 補助線(縦線)
                        color: "rgba(255, 0, 0, 0.2)",   // 補助線の色
                        zeroLineColor: "black"           // x=0時の(縦線の色)
                    },
                    ticks: {
                        beginAtZero: true,
                        min: 0,
                        max: 100,
                    },
                }],
                yAxes: [{
                    gridLines: {                       // 補助線(縦線)
                        color: "rgba(255, 0, 0, 0.2)",   // 補助線の色
                        zeroLineColor: "black"           // x=0時の(縦線の色)
                    },
                    ticks: {
                        beginAtZero: true,
                        min: 0,
                        max: 100,
                        stepSize: 10,
                    },
                }],

            },
        }
    });
};

とりあえずサンプルなので、データは「Math.floor( Math.random()*100 )」で0から99迄の乱数を発生させて作ってます。

肝心の、canvasのサイズ指定は

ctx.canvas.width=500;
ctx.canvas.height=500; 

 でいけました。

あと、軸の設定まわり(scalesとかxAxesとか)の説明は、こちらにあります。

misc.0o0o.org

転記はしていませんので、参照ください。

今回はこんなところで。

ではでは。