Googleのdoodle”Martha Graham”のjavascriptを自作

Googleの今日のdoodle「マーサ・グレアムの鉄山靠誕生日」が、大変気になったので自分でも実装できないか、Firebug片手に解析しながら実装してみました。
(一部で話題になってますね)

以下、コードです。

コード

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript">
// [left, top, width, height, scroll-x, scroll-y]
var grid = [
	[307, 48, 88, 89, 0, 0],
	[307, 48, 89, 89, -88, 0],
	[307, 48, 91, 89, -177, 0],
	[305, 49, 93, 89, -268, 0],
	[305, 50, 93, 88, -361, 0],
	[305, 50, 93, 88, -454, 0],
	[306, 52, 92, 86, -547, 0],
	[305, 53, 93, 84, -639, 0],
	[305, 54, 94, 83, -732, 0],
	[306, 54, 93, 83, -826, 0],
	[307, 54, 92, 83, -919, 0],
	[307, 54, 92, 83, -1011, 0],
	[308, 54, 90, 83, -1103, 0],
	[308, 54, 90, 83, -1193, 0],
	[306, 53, 91, 84, -1283, 0],
	[306, 53, 91, 84, -1374, 0],
	[308, 53, 90, 84, -1465, 0],
	[308, 53, 90, 84, -1555, 0],
	[305, 53, 92, 84, -1645, 0],
	[305, 52, 92, 85, -1737, 0],
	[306, 52, 91, 85, -1829, 0],
	[308, 51, 88, 87, -1920, 0],
	[308, 50, 88, 88, 0, -89],
	[308, 49, 88, 88, -88, -89],
	[307, 49, 89, 88, -176, -89],
	[307, 50, 89, 87, -265, -89],
	[308, 51, 89, 86, -354, -89],
	[307, 54, 90, 83, -443, -89],
	[307, 57, 90, 80, -533, -89],
	[306, 58, 92, 79, -623, -89],
	[306, 58, 92, 79, -715, -89],
	[305, 60, 92, 77, -807, -89],
	[302, 61, 95, 76, -899, -89],
	[302, 63, 95, 74, -994, -89],
	[302, 51, 96, 86, -1089, -89],
	[302, 66, 98, 71, -1185, -89],
	[304, 67, 96, 69, -1283, -89],
	[301, 63, 96, 74, -1379, -89],
	[301, 58, 93, 79, -1475, -89],
	[291, 52, 94, 85, -1568, -89],
	[288, 50, 71, 88, -1662, -89],
	[285, 43, 76, 95, -1733, -89],
	[285, 37, 70, 101, -1809, -89],
	[281, 29, 55, 109, -1879, -89],
	[278, 20, 58, 119, -1934, -89],
	[278, 20, 55, 119, -1992, -89],
	[277, 12, 121, 127, 0, -208],
	[271, 2, 122, 138, -121, -208],
	[267, 1, 126, 139, -243, -208],
	[264, 0, 136, 140, -369, -208],
	[260, 0, 141, 140, -505, -208],
	[255, 0, 148, 140, -646, -208],
	[252, 0, 151, 140, -794, -208],
	[249, 2, 121, 138, -945, -208],
	[247, 3, 123, 137, -1066, -208],
	[246, 3, 123, 137, -1189, -208],
	[246, 2, 124, 137, -1312, -208],
	[258, 2, 112, 137, -1436, -208],
	[263, 2, 106, 137, -1548, -208],
	[263, 2, 106, 137, -1654, -208],
	[262, 2, 103, 137, -1760, -208],
	[260, 2, 104, 136, -1863, -208],
	[260, 2, 104, 137, -1967, -208],
	[268, 2, 98, 137, 0, -348],
	[267, 2, 99, 137, -98, -348],
	[266, 2, 97, 137, -197, -348],
	[266, 3, 96, 136, -294, -348],
	[264, 3, 99, 136, -390, -348],
	[263, 3, 100, 136, -489, -348],
	[261, 3, 100, 136, -589, -348],
	[259, 2, 138, 137, -689, -348],
	[254, 2, 126, 137, -827, -348],
	[247, 2, 101, 136, -953, -348],
	[240, 2, 108, 136, -1054, -348],
	[238, 1, 110, 137, -1162, -348],
	[230, 1, 118, 138, -1272, -348],
	[220, 15, 128, 124, -1390, -348],
	[211, 18, 137, 121, -1518, -348],
	[205, 43, 102, 96, -1655, -348],
	[202, 45, 104, 93, -1757, -348],
	[200, 38, 97, 101, -1861, -348],
	[198, 38, 104, 101, -1958, -348],
	[197, 39, 107, 100, 0, -486],
	[197, 39, 112, 100, -107, -486],
	[213, 39, 94, 110, -219, -486],
	[212, 40, 95, 111, -313, -486],
	[211, 41, 97, 111, -408, -486],
	[209, 42, 99, 112, -505, -486],
	[209, 43, 98, 112, -604, -486],
	[213, 43, 87, 112, -702, -486],
	[213, 42, 83, 113, -789, -486],
	[211, 40, 86, 109, -872, -486],
	[211, 38, 86, 103, -958, -486],
	[211, 37, 88, 112, -1044, -486],
	[211, 20, 186, 131, -1132, -486],
	[213, 27, 167, 122, -1318, -486],
	[212, 44, 87, 105, -1485, -486],
	[210, 44, 88, 98, -1572, -486],
	[195, 44, 106, 98, -1660, -486],
	[189, 44, 110, 98, -1766, -486],
	[182, 46, 117, 99, -1876, -486],
	[173, 44, 118, 96, -1993, -486],
	[161, 43, 130, 99, 0, -617],
	[154, 42, 137, 97, -130, -617],
	[153, 42, 137, 97, -267, -617],
	[153, 42, 137, 97, -404, -617],
	[152, 41, 137, 98, -541, -617],
	[151, 41, 137, 97, -678, -617],
	[149, 41, 145, 97, -815, -617],
	[148, 25, 144, 114, -960, -617],
	[148, 13, 144, 126, -1104, -617],
	[141, 12, 153, 127, -1248, -617],
	[115, 11, 173, 128, -1401, -617],
	[108, 7, 180, 133, -1574, -617],
	[108, 4, 180, 136, -1754, -617],
	[108, 3, 176, 137, -1934, -617],
	[108, 1, 161, 139, 0, -754],
	[105, 1, 235, 138, -161, -754],
	[103, 1, 295, 148, -396, -754],
	[103, 0, 277, 149, -691, -754],
	[108, 0, 234, 137, -968, -754],
	[101, 0, 232, 137, -1202, -754],
	[99, 0, 135, 139, -1434, -754],
	[95, 0, 244, 139, -1569, -754],
	[81, 0, 152, 139, -1813, -754],
	[69, 0, 164, 139, -1965, -754],
	[66, 0, 169, 139, 0, -903],
	[65, 0, 170, 139, -169, -903],
	[63, 0, 168, 138, -339, -903],
	[61, 0, 159, 138, -507, -903],
	[35, 0, 304, 139, -666, -903],
	[19, 0, 189, 140, -970, -903],
	[18, 11, 138, 129, -1159, -903],
	[18, 11, 137, 129, -1297, -903],
	[18, 11, 137, 128, -1434, -903],
	[18, 6, 135, 133, -1571, -903],
	[7, 4, 146, 136, -1706, -903],
	[6, 4, 147, 136, -1852, -903],
	[3, 4, 150, 136, -1999, -903],
	[3, 5, 150, 135, 0, -1043],
	[3, 8, 150, 132, -150, -1043],
	[4, 6, 394, 145, -300, -1043],
	[12, 6, 388, 145, -694, -1043],
	[11, 8, 389, 144, -1082, -1043],
	[11, 8, 387, 144, -1471, -1043],
	[11, 8, 387, 143, -1858, -1043],
	[10, 8, 113, 131, 0, -1188],
	[11, 8, 111, 131, -113, -1188],
	[10, 9, 112, 130, -224, -1188],
	[12, 9, 116, 130, -336, -1188],
	[12, 9, 111, 130, -452, -1188],
	[12, 9, 111, 130, -563, -1188],
	[12, 9, 110, 131, -674, -1188],
	[12, 34, 113, 106, -784, -1188],
	[13, 35, 110, 104, -897, -1188]
];

var index = 0;

(function(){
	var draw = function(){
		var hplogo = document.getElementById("hplogo");
		
		var element = document.createElement('div');
		element.style.left   = grid[index][0];
		element.style.top    = grid[index][1];
		element.style.width  = grid[index][2];
		element.style.height = grid[index][3];
		element.style.background = "url('http://www.google.co.jp/logos/2011/graham11-hp-sprite.png') no-repeat scroll " 
			+ grid[index][4] + "px " + grid[index][5] + "px transparent";
		hplogo.appendChild(element);
		
		index++;
		
		if(index < grid.length){
			setTimeout(draw, 50);
		}
	};
	
	window.onload = draw;
})();
</script>
<style>
#hplogo div{ position: absolute;}
</style>
</head>
<body>
<div id="hplogo" style="width: 403px; height: 156px;"></div>
</body>
</html>

コードの使い方

上のコードを適当なhtmlファイルにするとともに、
http://www.google.co.jp/logos/2011/graham11-hp-sprite.png
からスプライトpngをダウンロードしてsprite.pngにリネームした物を、先ほどのhtmlファイルと同列に置けば動きます。1フレームを50ミリ秒にしてあるので、本物よりも速くダンスします。
(5/12 追記)
上記ソースコードを修正して、pngファイルのダウンロードを不要にしました。
あと↓に置いたので、即見れます。
http://kcha2speedster.digi2.jp/mytest_doodle_martha_graham/

アニメーションの仕組み解説

仕組みを簡単に言ってしまうと、幅403ピクセル、高さ156ピクセルの描画用空間(div)の中に、約150個の小さなdivを絶対位置指定でどんどんと上書きしていきます。
各個の小さなdivの背景はスプライトpngファイルにして、指定位置にcssでスライドさせることで、スプライトpngから上書きに必要な各コマをくり抜くようなテクニックとなっています。

Eclipseで既存のAndroidプロジェクトを取り込むときの手順

File > New > Other からAndroid Projectを選択するよりも
File > Import からExisting Projects into Workspaceの方が好み。

前者は取り込み対象のプロジェクトの在り処がそのままになってしまうが、
後者は取り込んだプロジェクトを、プロジェクト置き場であるworkspaceにコピーする。

備忘録

入力データが0件の時の処理瑕疵について。
0件イコール0行と思っていたが、実データでは0件でも0列1行だった。

テストの際のデータについては、実運用データを取り寄せましょう、という話。