🧊

HTMLのCanvasについてのメモ

どうにもこうにも流行りの技術を使ってみたくて。

ただ一からやるには初心者には敷居が高すぎるので、先人のコードを読んで、いじってみることに。
お題はこちらから拝借!

canvasでキラキラした背景を作る方法 | tech.kayac.com - KAYAC engineers' blog

Canvasでガリガリ描写して、って使い方がまったくイメージわきません!
でもこんな風に背景として使ったり、ページのアクセントとしての使い方は素敵やなぁと思います。
なにはともあれそんな発想がすごいなぁー。

お世話になるコード

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script>
$(function () {
		
	var hyperspace = new Hyperspace();
	hyperspace.draw();
		
	$("#canv").fadeIn('fast');

});

var Hyperspace = function(){
	
	var canvas = document.getElementById('canv');
	var ctx = canvas.getContext('2d');
	
	//background
	ctx.fillRect(0, 0, canvas.width, canvas.height);
	
	var star = new Array(5);
	for( i=0; i<star.length; i++ ){
		star[i] = new Array(7);
		star[i][0] = Math.random()*canvas.width;	// x
		star[i][1] = Math.random()*canvas.height;	// y
		star[i][2] = Math.random()*canvas.width/3 + canvas.width/14;	// r
		star[i][3] = Math.random()*0.05 + 0.2;
		star[i][7] = true;
		var r = Math.random()*255;	// R
		var g = Math.random()*255;	// G
		var b = Math.random()*255;	// B
		r = Math.ceil(r);
		g = Math.ceil(g);
		b = Math.ceil(b);
		star[i][4] = r;		//r
		star[i][5] = g;		//g
		star[i][6] = b;		//b
	}
	
	//draw -------------------------------------
	var draw = function draw(){
		
		//reset
		ctx.globalCompositeOperation = "source-over";
		//ctx.fillStyle = "rgba(255, 255, 255, 1)";
		ctx.fillStyle = "rgba(0, 0, 0, 1)";
		ctx.fillRect(0, 0, canvas.width, canvas.height);
		
		ctx.globalCompositeOperation = "lighter";
		
		//point
		for(i=0; i<star.length; i++){
			ctx.beginPath();
			var edgecolor1 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.93)";
			var edgecolor2 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.6)";
			var edgecolor3 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.1)";
			var edgecolor4 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0)";
			var gradblur = ctx.createRadialGradient(star[i][0], star[i][1], 0, star[i][0], star[i][1], star[i][2]);
			gradblur.addColorStop(0,edgecolor1);
			gradblur.addColorStop(0.4,edgecolor1);
			gradblur.addColorStop(0.7,edgecolor2);
			gradblur.addColorStop(0.9,edgecolor3);
			gradblur.addColorStop(1,edgecolor4);
			ctx.fillStyle = gradblur;
			ctx.arc(star[i][0], star[i][1], star[i][2], 0, Math.PI*2, false);
			ctx.fill();
			
			
		}
		
	};
		
	return ({'draw': draw});
	
};
</script>

大きな流れ

  1. Canvasを描く場所を決める
  2. 今回は円を描くので、円の設定(色とか大きさとか)を決める
  3. 決められた設定の通りに描画する
  4. っていう一連の流れを実行!

1.Canvasを描く場所を決める

	var canvas = document.getElementById('canv');
	var ctx = canvas.getContext('2d');

お決まりのやつなので、そのまま覚える。
本家は画面サイズいっぱいに・・・っていうくだりがあるけどもここでは割愛。

2.円の設定

var star = new Array(5); //円の数
for( i=0; i<star.length; i++ ){
	star[i] = new Array(7);
	star[i][0] = Math.random()*canvas.width;	// 円のx座標
	star[i][1] = Math.random()*canvas.height;	// 円のy座標
	star[i][2] = Math.random()*canvas.width/3 + canvas.width/14;	// 円の半径r
	star[i][3] = Math.random()*0.05 + 0.2;
	star[i][7] = true;
	var r = Math.random()*255;	// R
	var g = Math.random()*255;	// G
	var b = Math.random()*255;	// B
	r = Math.ceil(r);
	g = Math.ceil(g);
	b = Math.ceil(b);
	star[i][4] = r;		//r
	star[i][5] = g;		//g
	star[i][6] = b;		//b
}

円を描くメソッドはコレ。

hoge.arc(x, y, radius, startAngle, endAngle, anticlockwise)
// x座標、y座標、半径、開始角度、終了角度、時計回りかどうか

これら7つを設定しなきゃだめ、と。
ただ円弧じゃなくて円を描くので、後ろ4つの値はどうでも良いというわけなのね。

後半は色の情報も一緒に作っている模様。
乱数作って、整数にして、格納、っと、
ここはもっと雑に一文で書けるとみた!

3.円の描画

ここからが肝心の。

var draw = function draw(){
		
	//reset
ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgba(0, 0, 0, 1)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
	
ctx.globalCompositeOperation = "lighter";

ド素人にはこの初期化処理の必要性がわかりません・・誰か教えてください!

最後の一文は描いたものの合成処理のされ方を指定するそうな。
この設定をlighterにしてるからこそ、ふわっとした光り方になってるみたい。

globalCompositeOperation プロパティ - Canvasリファレンス - HTML5.JP

//point
for(i = 0; i < star.length; i++){
	ctx.beginPath();
	var edgecolor1 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.93)";
	var edgecolor2 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.6)";
	var edgecolor3 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.1)";
	var edgecolor4 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0)";
	var gradblur = ctx.createRadialGradient(star[i][0], star[i][1], 0, star[i][0], star[i][1], star[i][2]);
	gradblur.addColorStop(0,edgecolor1);
	gradblur.addColorStop(0.4,edgecolor1);
	gradblur.addColorStop(0.7,edgecolor2);
	gradblur.addColorStop(0.9,edgecolor3);
	gradblur.addColorStop(1,edgecolor4);
	ctx.fillStyle = gradblur;
	ctx.arc(star[i][0], star[i][1], star[i][2], 0, Math.PI*2, false);
	ctx.fill();
}

挫折しそうw
こっちが本番の描画処理。

createRadialGradient(x0, y0, r0, x1, y1, r1) メソッドには 6 つの引数を与えます。
最初の 3 つの引数は、中心が (x0, y0) で半径が r0 の開始円を表します。
残りの3つは、中心が (x1, y1) で半径が r1 の終了円を表します。
その値は、座標空間の単位となります。
引数に、無限大や NaN がひとつでもあれば、NOT_SUPPORTED_ERR 例外が発生させなければいけません。
r0 または r1 のいずれかが負であれば、INDEX_SIZE_ERR 例外を発生させなければいけません。
そうでなければ、このメソッドは、指定の 2 つの円で初期化された円形の CanvasGradient オブジェクトを返さなければいけません。
createRadialGradient() メソッド - Canvasリファレンス - HTML5.JP

うん、わかんないw
最初に円の設定を作る時に、それぞれの円の色情報は作ってあったはず。
それを元に、円のグラデーションを指定している部分ということやと思う!

最初に設定値を作るところで、この設定もまとめて作っておけば良かったんじゃ?と思うものの、うーむ。

4.実行!

書いてある順番的には一番最初ですが、呼び出してこその関数なので、実行処理を忘れないようにしないと・・。

$(function () {
		
	var hyperspace = new Hyperspace();
	hyperspace.draw();
		
	$("#canv").fadeIn('fast');

});

単純に実行するんじゃなくて、newして実行してるのは、プログラムのお作法としてそうすべきってものやとは思うものの。

ちなみに、fadeInさせる意味もわかりません・・。

おわりに

これを読みといて思ったのは、

  • プロパティ多すぎ!みんなこれを覚えてるもんなんだろうか。
  • でもやってる内容は簡単。
  • 発想が素敵!
  • JavaScriptってなんでもできるんねー。

ちょっと気になる疑問を解消すべく、次回はサンプルを作ってみようと思います。