Canvasで色が変わるローディング画像を作ってみた。

ajaxによる非同期読み込みを実装して以来、こんどはajaxを読み込んでいる最中が長く感じるようになってきた。ページ切り替えてもどることを考えるとマシではあるが。だったらどうするか?描画を工夫するのが正解だろう。

そこで、Canvas でローディングイメージ(読み込み中の画像)のアニメーションを作成する [html5 の Canvas を使ってみる:第卌五回]のソースコードを改良して、色が七色に変わるローディングイメージを作ってみた。七色に変わるプログラムは、RainbowManを参考にした。

ブロードバンドよりも昔の時代は、文字や背景色を変化させては喜んでいた記憶があるが、はっきりいってウザイ。しかし、こういった新技術が発表されることで再び旧来の技術が生かされるときが来るものである。これをcanvasで描画したオブジェクトに反映させることで、単純なローディング画像が少しはマシになる。

IEの場合別途Modernizrと、excanvasが必要。

サンプル:canvas.html

<!DOCTYPE html>
<html lang="ja-JP" class="no-js">
	<head>
		<meta charset="UTF-8"/>
		<script type="text/javascript" src="modernizr-1.5.min.js"></script>
		<script type="text/javascript">
//<![CDATA[

(function(){
	if (!Modernizr.canvas) {
		document.write('<script type="text/javascript" src="excanvas.compiled.js"></'+'script>');
	}
}());

window.onload = function() {
	draw();
}

function draw() {
	// 大きさ(Canvas のサイズ)を指定
	var len = 256;
	// バーの本数
	var bars = 12;
	// 太さ
	var w = Math.round(len * 0.1);
	// 長さ
	var h = Math.round(len * 0.3);
	// 内側の円
	var r = len / 2;
	
	// ◇ 変化の度合い
	// 数字が小さいほど少しずつ変化。値は「2の n 剰」推奨。( 2, 4, 8, 16, 32....)
	var valLen  = 2;

	// ◇ 変化のスピード
	// 一秒は 1000。
	var timer   = 100;
	
	var ColorMin = 0;
	var ColorMax = 128;

	var temp	= new Array();
	// 色の順番
	var rgbOrder = ['b','g','r'];
	// 色の初期値
	var rgbLen  = {
		r	: 128,
		g	: 128,
		b	: 128
	};
	var seek	= 0;
	var plus	= true;
	
	// 色を rgb 形式で指定
	var color = "rgb(0, 0, 0)";

	// id: loading を変数 e に代入
	var e = document.getElementById("loading");
	e.width = len;
	e.height = len;
	// e で 2 次元描画を行うことの定義を変数 c に代入
	c = e.getContext('2d');
	// rotate(); の性質上、x:0、y:0 で回転させた方が良いので、
	// x:0、y:0 で描画させるものを Canvas の中央へ setTransform(); で移動
	c.setTransform(1, 0, 0, 1, r, r);
	
	// 透明度を入れる配列を変数 alphas に定義
	var alphas = [];
	
	(loadingTimer = function()
	{
		// 色を計算
		i = rgbOrder[seek];
		rgbLen[i] += plus? valLen: valLen* -1;
		if (rgbLen[i] >= ColorMax || rgbLen[i] <= ColorMin )
		{
			if (rgbLen[i] > ColorMax) rgbLen[i] = ColorMax;
			else if (rgbLen[i] < ColorMin) rgbLen[i] = ColorMin;
			plus = !plus;
			seek = !seek? 2: --seek;
		}
		// 色を出力
		color = 'rgba('+rgbLen['r']+','+rgbLen['g']+','+rgbLen['b']+',';

		// 描画されているものを clearRect(); で消去
		c.clearRect(-r, -r, (r * 2), (r * 2));

		for (var i = 0; i < bars; i++) {
			// alphas の値が揃っていなければ(最初の描画時)、alphas に透明度を追加
			if (alphas.length < bars){ alphas.push(i / bars); }
			// colorRGB の後ろに透明度を付けて透明度付きの色を定義
			var thisColor = color  + alphas[i] + ")";
			// fillStyle で色を指定
			c.fillStyle = thisColor;
			// strokeStyle で枠線に transparent を指定し無効化
			c.strokeStyle = "rgba(0,0,0,0)";
			// 描画開始
			c.beginPath();
			// 上記の形を lineTo(); と quadraticCurveTo(); と closePath(); で描画
			c.moveTo((0 - w / 4), (r - h));
			c.quadraticCurveTo(0, (r - h - w / 2), (0 + w / 4), (r - h));
			c.lineTo((0 + w / 2), (r - w / 3));
			c.quadraticCurveTo(0, (r + w / 3), (0 - w / 2), (r - w / 3));
			c.closePath();
			// fill(); と stroke(); で色付け
			c.fill();
			c.stroke();
			c.rotate((360 / bars) * Math.PI / 180);
		}
		// alphas の最後の要素を取得し、削除し、先頭へ追加
		alphas.splice(0, 0, alphas[bars]).pop();
		setTimeout(loadingTimer, timer);
	
	})();
}

// 描画を止める処理
function stopLoading() {
	clearInterval(loadingTimer);
}
//]]></script>
		<title>CANVAS test</title>
	</head>
	<body>
		<h1>canvas test</h1>
		<canvas id="loading">Canvas</canvas>
	</body>
</html>