2020-07-31 2020-08-01
CreateJSで雪が降る様子を表現する
HTML5 Canvasでリッチコンテンツを表現するためのJavaScriptライブラリ群であるCreateJS。今回はそのCreateJSを使用して、雪が降る様子を表現するサンプルをご紹介します。
ライブラリの読み込みとクラス設計
まずCreateJSのライブラリを読み込みます。今回はCDNを利用します。
head内にscriptタグを用意しておきます。
また今回はオブジェクト指向の練習も兼ねて、クラスを利用して設計していきます。
// 雪のクラス
class Snow extends createjs.Shape {
constructor() {
super();
this.positionX = Math.random() * 600;
this.positionY = -10;
this.speed = 1 + Math.random() * 2; // 雪が降るスピード
this.size = 1 + Math.random() * 5; // 雪のサイズ
this.angle = Math.random() * 3; // 雪の揺れの計算角度
this.angleSpeed = 0.02 + Math.random() * 0.08; // 揺れの変化スピードをランダムにする
this.swingWidth = 12 + Math.random() * 15; // 揺れの大きさ
this.drift = -1 + Math.random(); // X軸の向きへの加算
this.life = 1; // 生存フラグ
// 円を描画する
this.graphics
.beginFill("#fff")
.drawCircle(this.positionX, this.positionY, this.size);
}
// 雪が落下する動き
move() {
this.y += this.speed;
this.angle += this.angleSpeed;
// 少しづつ斜めに落ちる
this.positionX += this.drift;
// 横に揺れながら落下する
this.x = this.positionX + Math.sin(this.angle) * this.swingWidth;
if (this.y > stage.canvas.height) {
// canvasより下に落ちるとlifeを0にする
this.life = 0;
}
}
}
createjs.Shapeを継承したクラスを定義し、constructorメソッド内で雪一粒ごとのプロパティを設定し、drawCircleで円を描画します。
一粒ごとに大きさや動きのスピードを変化させたいため、Math.random関数でランダムな値をセットします。
雪が落下するmove関数では、Math.sin関数を使用してふわふわと横に揺れる動きをつけています。またY座標がcanvasの高さよりも大きくなると (canvasより下に落ちると)位置をリセットするために一旦ライフを0にします。
イベントリスナーを設定し、画面を更新する
window.addEventListener('load', init);
let snows = [];
let stage = null;
function init() {
// Stageオブジェクトを作成
stage = new createjs.Stage('snowCanvas');
stage.autoClear = false;
// 背景画像
let background = new createjs.Bitmap('./img/snow_bg.png');
stage.addChild(background);
// 雪を降らす
let snowTimer = setInterval(addSnow, 300);
function addSnow() {
let snow = new Snow();
snows.push(snow);
stage.addChild(snow);
if (snows.length >= 100) {
clearInterval(snowTimer);
}
}
// 自動的に画面更新する
createjs.Ticker.addEventListener('tick', render);
}
// 画面を更新する
function render() {
stage.update();
for (let i=0; i<snows.length; i++) {
// canvas内に存在していれば落下を実行
if (snows[i].life === 1) {
snows[i].move();
}
else {
// canvas外にいると位置をリセット
snows[i].x = Math.random() * 600;
snows[i].y = -10;
snows[i].life = 1;
}
}
}
ページの読み込みが完了したらinit関数を呼び出すイベントリスナーを設定しておきます。
init関数内ではStageオブジェクトを作成し、背景画像を追加します。
そして先ほど設計した雪クラスのインスタンスを作成し、用意しておいたsnows配列に追加するとともにstageに追加します。
このとき、一気に雪が発生しないようにsetInterval関数を使用して、300ミリ秒ごとに一つ発生するようにタイマーを設定します。そして100個以上に
なるとタイマーを停止させ、これ以上雪を発生させないようにします。
あとはcreatejs.Tickerクラスにイベントリスナーを設定し、tickイベントを監視します。tickイベントが発生するたびに
(今回の場合はデフォルト設定のため24FPS=1秒間に24回)render関数を呼び出して画面を更新、雪を落下させます。
このときに雪の生存フラグをチェックし、canvas外に出たときには位置をリセットして再度降らせるようにします。
参考サイト
CreateJSの基本的な使い方はics.mediaさんの記事が非常に参考になります。
https://ics.media/tutorial-createjs/