JavaScript:canvasに雪の結晶を降らせる

  • このエントリーをはてなブックマークに追加
  • LINEで送る

canvas上の指定した位置に画像を描画できる、ということで前回作った「JavaScript:雪がたくさん降る」を雪の結晶画像に変更した。

タッチで別ウインドウ表示
snow2

前回arcメソッドで描いた円が雪の代わりだったので、雪の結晶画像に変えたとたんに幻想的な風景になった。やはり見た目は大事だ

JavaScriptのImageオブジェクトは、画像ファイルの設定後すぐに画像が読み込まれるわけではないので、onloadメソッドできちんと読み込んだ後に処理を続行する必要がある。
(imgSnowは、Imageオブジェクト)

	// 雪の画像生成
	imgSnow.src = IMG_SNOW;
	imgSnow.onload = function(){
		g.drawImage(imgSnow, -1000, -1000);
	};

ちなみに、ときどき別の「何か」が降ってくる。

HTML部分

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="snow.js"></script>
<title>snowy2</title>
<style>
#canvas {
	border: solid 1px #000;
	margin: 32px;
}
</style>
 
</head>
<body>
	<canvas id="canvas" width="320" height="480"></canvas>
</body>
</html>

JavaScript部分

// -------------------------------------------------------------------------
// snow.js 雪がたくさん降る2(画像をcanvasに描画)
//
// 					created at 2013-12-26 on torisky.com
// -------------------------------------------------------------------------

/*
 * グローバル変数
 */
var canvas = null;					// キャンバス
var g = null;						// コンテキスト
var $id = function(id){ return document.getElementById(id); };
var title;							// タイトル文字列
var objectList = [];				// 雪オブジェクト管理用
var probability;					// 雪の発生確率
var imgSnow = new Image();		// 雪の画像用
var imgButa = new Image();		// ブタの画像用

/*
 * 定数
 */
var SCREEN_WIDTH = 320;
var SCREEN_HEIGHT = 480;
var TICK = 1000/30;
var IMG_SNOW = "snow32.png";
var IMG_BUTA = "buta.png";

/*
 * リセット関数
 */
var reset = function(){
	title = "snowy";
	objectList = [];
	probability = 0.95;	// 雪の発生確率
	// 雪の画像生成
	imgSnow.src = IMG_SNOW;
	imgSnow.onload = function(){
		g.drawImage(imgSnow, -1000, -1000);
	};
	// ブタの画像生成(おまけ)
	imgButa.src = IMG_BUTA;
	imgButa.onload = function(){
		g.drawImage(imgButa, -1000, -1000);
	};
	
	g.clearRect(0, 0, canvas.width, canvas.height);
};

/*
 * 情報表示
 */
var showInformation = function(){
	g.fillStyle = "rgba(0, 0, 0, 0.5)";
	g.fillText(title, 145, SCREEN_HEIGHT/ 2);
	g.fillText("ObjectList: " + objectList.length, 24, 24);
	var kakuritu = 100-(probability*100);
	g.fillText(kakuritu + "%     <- Click to change!", 24, 48);
};

/*
 * オブジェクト追加関数
 */
var addObject = function(obj){
	for(var i=0; i<objectList.length+1; i++){
		if(objectList[i] == null){
			objectList[i] = obj;
			console.log("addObject() " + i);
			break;
		}
	}
};

/*
 * 雪クラス
 */
var Snow = function(sx, sy, _image){
	var speed = Math.floor(Math.random() * 5) + 1;	// 落下速度 1~5
	var yure = Math.floor(Math.random() * 3) + 1;	// ゆれ 1~3
	// 雪の初期位置
	var x = sx;
	var y = sy;
	var image = new Image();
	image = _image;
	// 雪が降る
	this.move = function(){
		// 雪を描く
		g.drawImage(_image, x, y);
		// 雪の軌跡を計算
		x = x + Math.sin((y + speed) * Math.PI/180) * yure;
		y = y + speed;
		if(y > SCREEN_HEIGHT){
			return false;
		}
		return true;
	};
};

/*
 * マウスクリック/タッチ時の処理
 */
var ontouch = function(x, y){
	var kakuritu = Math.floor(Math.random() * 100) + 1;
	kakuritu /= 100;
	probability = kakuritu;
};

/*
 * メイン処理
 */
var mainLoop = function(){
	g.fillStyle = "rgb(200, 200, 200)";
	g.fillRect(0, 0, canvas.width, canvas.height);
	showInformation();
	// オブジェクトの動作と消去
	for(var i=0; i<objectList.length; i++){
		var obj = objectList[i];
		if(obj && !obj.move()){
			delete objectList[i];
		}
	}
	// 雪の生成
	if(Math.random() > probability){
		if(Math.random() > 0.99){		// ときどきブタ!
			addObject(new Snow(Math.random() * SCREEN_WIDTH, 0-Math.random()*150, imgButa));
		}
		else{
			addObject(new Snow(Math.random() * SCREEN_WIDTH, 0-Math.random()*150, imgSnow));
		}
	}
	setTimeout(mainLoop, TICK);
};

/*
 * 起動処理
 */
window.onload = function(){
	// キャンバス情報取得
	canvas = $id("canvas");
	g = canvas.getContext("2d");

	// 雪を降らせる
	reset();
	mainLoop();
	// タッチイベント処理
	canvas.onmousedown = function(e){
		ontouch(e.clientX, e.clientY);
	};
	canvas.ontouchstart = function(e){
		if(e.touches[0]){
			ontouch(e.touches[0].clientX, e.touches[0].clientY);
		}
		e.preventDefault();
	};

};
  • このエントリーをはてなブックマークに追加
  • LINEで送る

SNSでもご購読できます。

コメントを残す