見出し画像

Canvas+JavaScriptで多角形/星型多角形を描いた話

はじめに

JavaScriptとCanvasの練習がてら、多角形/星形多角形を描いて遊びました。

具体的には下記を実装してみました。
・円と線分を描く
・1秒ごとに頂点の数を増やす
・隣の頂点と繋ぐ/隣の隣と繋ぐ…とN個飛ばしで頂点をつなげるようにする


頂点0個飛ばし(多角形)
頂点1個飛ばし(星形多角形)


頂点2個飛ばし(星形多角形)

html

ヘッダー画像のページを作ります。
canvasが上下中央に配置されるように、body要素に高さを指定(横幅は勝手にされる)。flexを指定して子要素のcanvasが上下中央に来るようにしました。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Draw star</title>
    <style>
        body{
            margin: 0px;
            padding: 0px;
            background: #b0c4de;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }  
        #canvas{
            border: 1px solid #c2d6ef;
        }
  </style>
</head>
<body>
    <canvas id="canvas"></canvas>    
    <script type="text/javascript" src="main.js"></script>
</body>
</html>

JavaScript

"use strict";

// async/awaitでループ中にスリープしつつ
// draw関数を呼び出す
(async () => {
    let i = 3;
    while (true) {
        draw(i, 3);
        await wait(1000);	// 1秒ごとに描写
        i++;
    }
})();
function wait(msec) {
    return new Promise(resolve => setTimeout(resolve, msec));
}

// 頂点数vertices、頂点を(skip-1)個飛ばしで繋いだ図を描写する
function draw(vertices, skip) {
    console.log(vertices);

    // パラメータ
    const height = 1000;
    const width  = 1000;
    const radius = Math.min(height, width)/2;

    // canvasのお作法
    const cvs = document.getElementById('canvas');  // canvas要素への参照の取得
    const ctx = canvas.getContext('2d');            // コンテキストの取得
    cvs.width = width;
    cvs.height = height;

    // 円周を描写
    ctx.beginPath();
    ctx.arc(height/2, width/2, radius, 0, 2*Math.PI);
    ctx.closePath();
    ctx.stroke();

    // 頂点の座標を格納する配列を作成
    let verticesPos = [];
    let i;
    for(let i=0; i<vertices; i++){
        if(vertices == 1) break;
        var rad = 2*Math.PI / vertices;
        verticesPos.push([height/2 + radius*Math.sin(rad*i)  , width/2 - radius*Math.cos(rad*i) ]);
    }

    // 線を描写
    for(i=0; i<vertices; i++){
        // 頂点数がスキップ数以下だったら描写しない
        if(vertices <= skip){ break; };

        // スキップした先が配列の要素数を超えた場合の処理
        // (450度→90度にするようなイメージ)
        let j = i + skip;
        if(j>=vertices){ j = j -vertices; };

        // 線分を描写
        ctx.beginPath();
        ctx.moveTo(verticesPos[i][0], verticesPos[i][1]);   // ペンを点Iへ移動
        ctx.lineTo(verticesPos[j][0], verticesPos[j][1]);   // 点Iから点Jへ線を引く
        ctx.stroke();
    }
}


この記事が気に入ったらサポートをしてみませんか?