LoginSignup
2
1

More than 3 years have passed since last update.

canvasでクリスマスツリーをチカチカさせた習作

Posted at

はじめに

クリスマスだし、なんとなくそれっぽいことをしたい気持ちです。
ずっと仲良くなりたいと思っていたcanvasを使って、クリスマスツリーをチカチカさせてみようかと思います。

xmas_tree.gif

詳細

index.html

canvasを設置して、bodyのonloadに仕掛けた初期化用の関数を実行するだけです。

index.html
<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で一定間隔で再描画しています。

main.js
// 省略
const interval = 500;  // 明滅間隔(ミリ秒)
// 省略
function initialize() {
  treeImage.src = 'tree.png'

  window.setInterval(draw, interval);
}
// 省略

描画

一度白紙に戻してから、木の絵を書いて、明かりを描画しています。
明かりの位置は…テキトーに描いた絵だったので、機械的に決められず…座標を保持しています。
明かりは60%の確率でついているようにしています。

本当は見えないcanvasに一通り書き終わってから、見えるcanvasにコピーするなどしたほうがちらつきが抑えられるかもしれませんが、平気そうだったのでやってません。

main.js
// 省略
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、楽しい!

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1