よくある一筆書きで描くような星型(☆)をキャンバスに描画する方法です。
まずは基本サンプルをご覧ください。
基本のソースコード
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="main.js"></script>
<title>星をキャンバスに描画基本</title>
<style>
*{ margin: 0; padding: 0; }
</style>
</head>
<body>
<canvas id="canvas" width="480" height="480"></canvas>
</body>
</html>
main.js
// main.js
let canvas, g;
// 星を描画する関数(中心x座標、中心y座標、半径、色)
const drawStar = function(cx, cy, r, color){
let theta = -90; // 角度修正(キャンバスでは3時方向が0度扱いのため12時方向を0度とする)
let star = [];
while(star.length < 5){ // 星の5つの頂点を求める
const pos = {
x: r * Math.cos(theta*Math.PI/180) + cx,
y: r * Math.sin(theta*Math.PI/180) + cy,
};
star.push(pos);
theta += 72; // 次の点の位置:360度 ÷ 5 = 72度
}
// 星を描画する
g.fillStyle = color;
g.beginPath(); // パスの開始
g.moveTo(star[0].x, star[0].y);
g.lineTo(star[2].x, star[2].y);
g.lineTo(star[4].x, star[4].y);
g.lineTo(star[1].x, star[1].y);
g.lineTo(star[3].x, star[3].y);
g.closePath(); // パスを閉じる
g.fill();
}
window.addEventListener("load", ()=>{
// キャンバスの初期設定
canvas = document.getElementById("canvas");
g = canvas.getContext("2d");
// 背景色描画
g.fillStyle = "midnightblue";
g.fillRect(0, 0, canvas.width, canvas.height);
// 星を描画
drawStar(240, 240, 80, "yellow");
});
星を描画する考え方とソースコードへの応用
まず中心(cx, cy)とした星の5つの頂点を通る円を考えます。
5等分するわけですから12時方向を最初の頂点(図の0番)とおくと72度ずつ時計回りにずらして1番から4番まで等間隔で頂点を求めることができます。(ソースコード上でもこの0~4の番号を配列starの添え字としているので分かりやすいかと思います)
72度というのは、
360度 ÷ 5等分 = 72度
だからです。
具体的には円周の0度、72度、144度、216度、288度の5つを頂点とします。
円周上のある角度(Θ)の座標(x, y)は、円の半径(r)、円の中心座標(cx, cy)が分かれば次の式で求めることができます。
x = r * cos(Θ) + cx y = r * sin(Θ) + cy
この式で求めた5つの頂点は使いやすいように配列star[0]~[4]に保存しておきます。
実際のソースコード部分
let theta = -90;
let star = [];
while(star.length < 5){ // 星の5つの頂点を求める
const pos = {
x: r * Math.cos(theta*Math.PI/180) + cx,
y: r * Math.sin(theta*Math.PI/180) + cy,
};
star.push(pos);
theta += 72; // 次の点の位置:360度 ÷ 5 = 72度
}
星の頂点が求められたら、あとはキャンバスへの描画ですが、これにはmoveTo, lineToメソッドを使います。
変数theta(角度)を最初に-90としているのは、JavaScriptのキャンバスの仕様と関係があります。
キャンバスでは3時方向(右方向)の角度が0度という扱いです。12時方向を0度とするために反時計まわりに90度(-90度)にして調整しています。
最後に星の描画ですが、キャンバスのmoveToメソッドで最初の点(0番)に移動して、あとはlineToメソッドを使い
0番 → 2番 → 4番 → 1番 → 0番
と順番に一筆書きの要領で描画していきます。
最後に始点の0番に戻る部分は、closePathメソッドでOKです。
ソースコード上での描画部分
// 星を描画する g.fillStyle = color; g.beginPath(); // パスの開始 g.moveTo(star[0].x, star[0].y); // ここが始点 g.lineTo(star[2].x, star[2].y); g.lineTo(star[4].x, star[4].y); g.lineTo(star[1].x, star[1].y); g.lineTo(star[3].x, star[3].y); g.closePath(); // パスを閉じる(始点に戻る) g.fill();
星をいろいろな形で描画
今回星型(☆)を描画する部分をdrawStarという名称に関数化してあります。
せっかくなので活用してみたいと思います。
星をランダムな位置に描画
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="main.js"></script>
<title>星をキャンバスにランダムで描画</title>
<style>
*{ margin: 0; padding: 0; }
</style>
</head>
<body>
<canvas id="canvas" width="480" height="480"></canvas>
</body>
</html>
main.js
// main.js
let canvas, g;
// 星を描画する関数(中心x座標、中心y座標、半径、色)
const drawStar = function(cx, cy, r, color){
let theta = -90; // 角度修正(キャンバスでは3時方向が0度扱いのため12時方向を0度とする)
let star = [];
while(star.length < 5){ // 星の5つの頂点を求める
const pos = {
x: r * Math.cos(theta*Math.PI/180) + cx,
y: r * Math.sin(theta*Math.PI/180) + cy,
};
star.push(pos);
theta += 72; // 次の点の位置:360度 ÷ 5 = 72度
}
// 星を描画する
g.fillStyle = color;
g.beginPath();
g.moveTo(star[0].x, star[0].y);
g.lineTo(star[2].x, star[2].y);
g.lineTo(star[4].x, star[4].y);
g.lineTo(star[1].x, star[1].y);
g.lineTo(star[3].x, star[3].y);
g.closePath();
g.fill();
}
window.addEventListener("load", ()=>{
// キャンバスの初期設定
canvas = document.getElementById("canvas");
g = canvas.getContext("2d");
// 背景色描画
g.fillStyle = "midnightblue";
g.fillRect(0, 0, canvas.width, canvas.height);
// ランダムな位置に星を描画
for(let i=0; i<30; i++){
let [x, y] = [Math.random()*canvas.width, Math.random()*canvas.height];
let r = Math.random() * 20 + 10; // 半径 10~30の範囲
drawStar(x, y, r, "yellow");
}
});
星を整列して描画
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="main.js"></script>
<title>星をキャンバスに整列して描画</title>
<style>
*{ margin: 0; padding: 0; }
</style>
</head>
<body>
<canvas id="canvas" width="480" height="480"></canvas>
</body>
</html>
main.js
// main.js
let canvas, g;
// 星を描画する関数(中心x座標、中心y座標、半径、色)
const drawStar = function(cx, cy, r, color){
let theta = -90; // 角度修正(キャンバスでは3時方向が0度扱いのため12時方向を0度とする)
let star = [];
while(star.length < 5){ // 星の5つの頂点を求める
const pos = {
x: r * Math.cos(theta*Math.PI/180) + cx,
y: r * Math.sin(theta*Math.PI/180) + cy,
};
star.push(pos);
theta += 72; // 次の点の位置:360度 ÷ 5 = 72度
}
// 星を描画する
g.fillStyle = color;
g.beginPath();
g.moveTo(star[0].x, star[0].y);
g.lineTo(star[2].x, star[2].y);
g.lineTo(star[4].x, star[4].y);
g.lineTo(star[1].x, star[1].y);
g.lineTo(star[3].x, star[3].y);
g.closePath();
g.fill();
}
window.addEventListener("load", ()=>{
// キャンバスの初期設定
canvas = document.getElementById("canvas");
g = canvas.getContext("2d");
// 背景色描画
g.fillStyle = "midnightblue";
g.fillRect(0, 0, canvas.width, canvas.height);
// キャンバス全体に星を整列描画
for(let i=0; i<10; i++){
for(let j=0; j<10; j++){
let [x, y] = [i*48+24, j*48+24];
drawStar(x, y, 24, "forestgreen");
}
}
});
星をランダムな位置にランダムカラーで描画
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="main.js"></script>
<title>星をキャンバスにランダムで描画(色もランダム)</title>
<style>
*{ margin: 0; padding: 0; }
</style>
</head>
<body>
<canvas id="canvas" width="480" height="480"></canvas>
</body>
</html>
main.js
// main.js
let canvas, g;
// ランダムカラー文字列を生成して返す関数
function getRandomColor(){
const get256 = ()=>{ return Math.floor(Math.random()*256); }; // 0 ~ 255を返す
let [r, g, b] = [get256(), get256(), get256()]; // ランダムでRGBカラーを設定
let color = `rgb(${r}, ${g}, ${b})`; // 文字列生成 'rgb(XX, XXX, XXX)'
return color;
}
// 星を描画する関数(中心x座標、中心y座標、半径、色)
const drawStar = function(cx, cy, r, color){
let theta = -90; // 角度修正(キャンバスでは3時方向が0度扱いのため12時方向を0度とする)
let star = [];
while(star.length < 5){ // 星の5つの頂点を求める
const pos = {
x: r * Math.cos(theta*Math.PI/180) + cx,
y: r * Math.sin(theta*Math.PI/180) + cy,
};
star.push(pos);
theta += 72; // 次の点の位置:360度 ÷ 5 = 72度
}
// 星を描画する
g.fillStyle = color;
g.beginPath();
g.moveTo(star[0].x, star[0].y);
g.lineTo(star[2].x, star[2].y);
g.lineTo(star[4].x, star[4].y);
g.lineTo(star[1].x, star[1].y);
g.lineTo(star[3].x, star[3].y);
g.closePath();
g.fill();
}
window.addEventListener("load", ()=>{
// キャンバスの初期設定
canvas = document.getElementById("canvas");
g = canvas.getContext("2d");
// 背景色描画
g.fillStyle = "midnightblue";
g.fillRect(0, 0, canvas.width, canvas.height);
// ランダムな位置に星を描画
for(let i=0; i<200; i++){
let [x, y] = [Math.random()*canvas.width, Math.random()*canvas.height];
let r = Math.random() * 20 + 10; // 半径 10~30の範囲
drawStar(x, y, r, getRandomColor() );
}
});
1つ作ると色々と応用ができて楽しいですね!
頑張ればJavaScriptのキャンバス機能だけでガーナ共和国の国旗も描画できますよ。
参考
以上、キャンバスに星型(☆)を描画するでした。
コメント