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

JavaScript

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

JavaScript:雪がたくさん降る
「JavaScriptにおいて関数はクラスと同義である」ということで、実際に「雪」クラス(関数)を作って雪がたくさん降ってくる様をcanvasに描いた。

サンプルを見る

前回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();
	};

};

コメント

タイトルとURLをコピーしました