はじめに
クリスマスだし、なんとなくそれっぽいことをしたい気持ちです。
ずっと仲良くなりたいと思っていたcanvasを使って、クリスマスツリーをチカチカさせてみようかと思います。
詳細
index.html
canvasを設置して、bodyのonloadに仕掛けた初期化用の関数を実行するだけです。
<html>
<head>
<!-- 省略 -->
<script src="main.js"></script>
</head>
<body onload='initialize();'>
<p>
<canvas id='tutorial' width='320' height='320'></canvas>
</p>
</body>
<html>
初期化
bodyのonloadで実行される部分です。
setInterval
で一定間隔で再描画しています。
// 省略
const interval = 500; // 明滅間隔(ミリ秒)
// 省略
function initialize() {
treeImage.src = 'tree.png'
window.setInterval(draw, interval);
}
// 省略
描画
一度白紙に戻してから、木の絵を書いて、明かりを描画しています。
明かりの位置は…テキトーに描いた絵だったので、機械的に決められず…座標を保持しています。
明かりは60%の確率でついているようにしています。
本当は見えないcanvasに一通り書き終わってから、見えるcanvasにコピーするなどしたほうがちらつきが抑えられるかもしれませんが、平気そうだったのでやってません。
// 省略
const lightPositions = [ // 明かりの位置
[128, 76], [158, 221], [150, 94], [174, 156], [177, 100],
[203, 161], [193, 224], [116, 140], [105, 195], [225, 224],
[157, 75], [164, 130], [155, 191], [186, 202], [208, 201],
[94, 229], [124, 238], [162, 250], [215, 247]
];
const lightRate = 0.6; // 明かりが光る割合
// 省略
function draw() {
var ctx = document.getElementById('tutorial').getContext('2d');
ctx.clearRect(0, 0, 320, 320);
ctx.drawImage(treeImage, 0, 0, 320, 320);
for(var i = 0; i < lightPositions.length; i++) {
if(Math.random() > lightRate) { continue; }
var [x, y] = lightPositions[i];
drawLight(ctx, x, y);
}
}
// 省略
明かりの描画
渡されたコンテキストに、指定の位置を中心に、決まった色で円を描いています。
少し色気を持たせたかったので、透明度を変えて円を描いています。
ここでハマったのはbeginPath()
です。これを最初適宜挟まなかったために、透明度が利かなかったり、円と円の間に線が書かれてしまったりしてました。
// 省略
const lightRadius = 3; // 明かりの半径
const aroundLightRadiusMagnification = 1.7; // 明かりの近い周辺
const outerLightRadiusMagnification = 3.0; // 明かりの遠い周辺
const lightColor = 'rgb(255, 255, 255)'; // 明かりの色
const aroundLightColor = 'rgba(255, 255, 255, 0.6)'; // 明かりの近い周辺の色
const outerLightColor = 'rgba(255, 255, 255, 0.2)'; // 明かりの遠い周辺の色
// 省略
function drawLight(ctx, x, y) {
ctx.beginPath();
ctx.fillStyle = outerLightColor;
ctx.strokeStyle = outerLightColor;
ctx.arc(x, y, lightRadius * outerLightRadiusMagnification, 0, 2 * Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = aroundLightColor;
ctx.strokeStyle = aroundLightColor;
ctx.arc(x, y, lightRadius * aroundLightRadiusMagnification, 0, 2 * Math.PI, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = lightColor;
ctx.strokeStyle = lightColor;
ctx.arc(x, y, lightRadius, 0, 2 * Math.PI, false);
ctx.fill();
}
終わりに
単純しか使わなかったですが、canvas、結構楽しいですね。
ちゃんとやれば、オブジェクトごとに描画、みたいな進化もさせられそう、などと思ったり思わなかったり…。
ゲームを作っているひとが結構いますが、たしかにわかる…。作りたくなってきました。
canvas、楽しい!