HTML5 Canvasで、レーダーチャートに使える正多角形を動的に描画してみた

シェアする

HTML5 Canvasで「chart.js」を使用しないでレーダーチャートを作成しました。
今回は、そのうちのプロットエリアを描画する関数を紹介したいと思います。

「canvas」「レーダーチャート」をキーワードにして作り方を検索したところ、「chart.js」という、いろんなグラフを描画出来るJavaScriptライブラリを見付けました。しかし今回の案件、「プロットした点が重なった時はずらして表示する等」、チャートの描画に関して色々細かい仕様があったため、「chart.js」は使わず、Canvasのみで書いてみようと試みました。

スポンサーリンク

サンプル

作ろうとしているものがこちらになります。
「頂点の数」「大きさ」等のパラメータを変更して「反映」を押すとチャートの形が変わるので、試してみてください。

[更新(2/2)] フォームの値を変更したら即チャートの形が変わるようにしました。

以下でこのチャートの作り方を説明して行きます。

各種ファイルを準備

以下のようにファイルを準備します。

┣ index.html
┗ js
   ┗ main.js

jQueryのファイルは、バージョン1.x.xとバージョン2.x.xで動作は確認できました。
バージョン3.x.xでは動作しませんでした、、、、。

[更新(2/2)] jQueryがなくても動くように変更しました。

このページ下部に、githubにあげたサンプルプロジェクトのリンクがあります。

index.htmlの記述

index.htmlは以下のように記述しておきます。
【index.html】

<html>
<head>
    <meta charset="utf-8">
    <script src="js/main.js"></script>
</head>
<body>
    <div>
        <canvas id="chart" height="800" width="1000"></canvas>
    </div>
</body>
</html>

jQueryとCanvas描画用ファイルmain.jsを読み込ませ、canvasタグの設置をします。
今回はcanvasの「height」を「800」、「width」を「1000」に設定しています。

main.jsの記述

まず下準備として以下のコードを入れておきます。
【main.js】

window.onload = function() {
    chartbuild();
};

function chartbuild() {

    var canvas = document.getElementById('chart');
    if (canvas.getContext) {

        var context = canvas.getContext('2d');

    }
}

ページが読み込まれた後に、chartbuild()の中の処理が行われます。
このchartbuild()の中に必要なコードを追加していきます。

チャートの基本設定

チャートを描画する場所、大きさ、頂点の数等の設定部分です。

    //チャートの基本変数定義
    var center_x = 500;          //中心x座標
    var center_y = 500;          //中心y座標
    var vertex = 5;              //頂点の数
    var size = 300;              //大きさ(外接円の半径)
    var tilt = 180;               //傾き(0だと1つ目の頂点が真下にくる)
    var scale = 5;               //目盛の数
    var line_color = "#a9a9a9";  //チャートのライン色
    var line_width = 3;          //チャートのラインの太さ
    var line_width_out = 8;      //チャートのラインの太さ(一番外側)
    var line_width_center = 2;   //チャートの中心線の太さ

チャートの枠と目盛線の描画

    function makechartframe(){

        var x;
        var y;
        var csize;
        var angle;
        var rad;
        context.strokeStyle = line_color;
        for (var k=scale;k>=0;k--) {
            csize = size / scale * k;
            context.beginPath();
            if (k == scale) {
                context.lineWidth = 8;  //一番外側のラインの太さ
            } else {
                context.lineWidth = 3;  //それ以外のラインの太さ
            }

            for (var l=0;l<vertex;l++) {

                angle = tilt + 360 / vertex * l;
                rad = angle * Math.PI / 180;

                x = center_x + Math.sin(rad) * csize;
                y = center_y + Math.cos(rad) * csize;

                if (l == 0) {
                    context.moveTo(x,y);
                    start_x = x;
                    start_y = y;
                } else {
                    context.lineTo(x,y);
                }

            }
            context.lineTo(start_x,start_y);
            context.stroke();
        }
    }

一番外側から内側にかけて、設定した目盛り分、多角形を描画する処理となっています。
(大きい多角形の内側に少しづつ小さい多角形を連続して描くイメージ)
「tilt」の設定が「0」だと1つ目の頂点が中心の真下からになります。
今回は1つ目の頂点を真上に持っていくために「tilt」の設定を「180」にしています。

中心線の描画

    //チャートの中心線を描画
    function makecenterline() {

        var x;
        var y;
        var angle;
        var rad;
        context.strokeStyle = line_color;
        context.lineWidth = line_width_center;
        for (var m=0;m<vertex;m++) {
            angle = tilt + 360 / vertex * m;
            rad = angle * Math.PI / 180;

            x = center_x + Math.sin(rad) * size;
            y = center_y + Math.cos(rad) * size;

            context.beginPath();
            context.moveTo(center_x,center_y);
            context.lineTo(x,y);
            context.stroke();
        }
    }

プロット表の中心から、一番外側の頂点へ線を引く処理をしています。

これまでのコードをマージ

【main.js】

window.onload = function() {
    chartbuild();
});

function chartbuild() {

    var canvas = document.getElementById('chart');
    if (canvas.getContext) {

        var context = canvas.getContext('2d');

        //チャートの基本変数定義
        var center_x = 500;          //中心x座標
        var center_y = 500;          //中心y座標
        var vertex = 5;              //頂点の数
        var size = 300;              //大きさ(外周円の半径)
        var tilt = 180;             //傾き
        var scale = 5;               //目盛の数
        var line_color = "#a9a9a9";  //プロット表のライン色
        var line_width = 3;          //プロット表のラインの太さ
        var line_width_out = 8;      //プロット表のラインの太さ(一番外側)
        var line_width_center = 2;   //プロット表の中心線の太さ

        reset();

        function reset() {
            makechartframe();
            makecenterline();
        }   


        //チャートの枠と目盛ラインを描画
        function makechartframe(){

            var x;
            var y;
            var start_x;
            var start_y;
            var csize;
            var angle;
            var rad;
            context.strokeStyle = line_color;
            for (var k=scale;k>=0;k--) {
                csize = size / scale * k;
                context.beginPath();
                if (k == scale) {
                    context.lineWidth = line_width_out;
                } else {
                    context.lineWidth = line_width;
                }

                for (var l=0;l<vertex;l++) {

                    angle = tilt + 360 / vertex * l;
                    rad = angle * Math.PI / 180;

                    x = center_x + Math.sin(rad) * csize;
                    y = center_y + Math.cos(rad) * csize;

                    if (l == 0) {
                        context.moveTo(x,y);
                        start_x = x;
                        start_y = y;
                    } else {
                        context.lineTo(x,y);
                    }

                }
                context.lineTo(start_x,start_y);
                context.stroke();
            }
        }

        //チャートの中心線を描画
        function makecenterline() {

            var x;
            var y;
            var angle;
            var rad;
            context.strokeStyle = line_color;
            context.lineWidth = line_width_center;
            for (var m=0;m<vertex;m++) {
                angle = tilt + 360 / vertex * m;
                rad = angle * Math.PI / 180;

                x = center_x + Math.sin(rad) * size;
                y = center_y + Math.cos(rad) * size;

                context.beginPath();
                context.moveTo(center_x,center_y);
                context.lineTo(x,y);
                context.stroke();
            }
        }

    }
}

reset()関数の中で、makechartframe()と、makecenterline()を呼んで描画しています。

まとめ

上記のプログラムでも、チャートの位置、大きさ、色、傾き、頂点の数、目盛りなど、色々とカスタマイズできるようになっております。
また、関数の中を少しいじればさらに細かくカスタマイズできると思います。

サンプルプロジェクト

githubに今回実装したサンプルプロジェクトがあります。

ブログ本文では解説していませんが、フォームの値を変更するとチャートに即時反映されるコードもサンプルには入っております。

Contribute to ChatLune/blog-javascript-canvasChart development by creating an account on GitHub.

適宜ご活用ください。

飲食業界からIT業界に転身してきて現在2年目です。PHPの経験がメインとなります。これまで自分がPHPを扱ってきた上で、モヤモヤしてきたことをメインに記事にしていきますのでよろしくお願いいたします。

スポンサーリンク

シェアする

フォローする