Google Doodle-Google首頁的javascript動畫初探

今天早上除了發現自己過了10:42還活著之外,還發現Google首頁的Google Doodle有了新的動畫,今天的主題是瑪莎·葛蘭姆(Martha Graham)117歲誕辰 (不認識XD),不過這種手繪風格的動畫實在太有質感了,因此除了非常好奇的去看作者是哪位仁兄外,也想趁這個機會了解google是如何撰寫這個javascript動畫。

一開始當然是從習慣性的檢視原始碼開始,很快的發現了script標籤,接著把該段程式format整理一下排版,就成了給人看的javascript程式碼。大致觀察一下程式碼,很快的就會發現它將所有動畫圖片都放在一張大png裡(看起來有點大,但其實不過300多k的容量),將多張小圖放進一張大圖來存取,這是常見提升網站讀取速度的作法。

除了大圖之外,觀察程式碼可以很容易的發現在變數取名及程式碼描述上的用法都很精簡,像是變數取名 a,b,c,d,e,f,g…,還有到處可見三元表示式,以及使用 && 取代 if 敘述等的作法。

<style>
#hplogo
{
	background:#020202;
	height:156px;
	position:relative;
	width:403px
}
#hplogo div
{
	pointer-events:none;
	position:absolute
}
</style>

<div id=hplogo></div>
<script>
window.google={};
(function(){
	try{
	if(!google.doodle)
		google.doodle={};

	var d=[[307,48,88,89],[307,48,89,89],[307,48,91,89],[305,49,93,89],[305,50,93,88],
		[305,50,93,88],[306,52,92,86],[305,53,93,84],[305,54,94,83],[306,54,93,83],[307,54,92,83],[307,54,92,83],
		[308,54,90,83],[308,54,90,83],[306,53,91,84],[306,53,91,84],[308,53,90,84],[308,53,90,84],[305,53,92,84],
		[305,52,92,85],[306,52,91,85],[308,51,88,87,1],[308,50,88,88],[308,49,88,88],[307,49,89,88],[307,50,89,87],
		[308,51,89,86],[307,54,90,83],[307,57,90,80],[306,58,92,79],[306,58,92,79],[305,60,92,77],[302,61,95,76],
		[302,63,95,74],[302,51,96,86],[302,66,98,71],[304,67,96,69],[301,63,96,74],[301,58,93,79],[291,52,94,85],
		[288,50,71,88],[285,43,76,95],[285,37,70,101],[281,29,55,109],[278,20,58,119],[278,20,55,119,1],[277,12,121,127],
		[271,2,122,138],[267,1,126,139],[264,0,136,140],[260,0,141,140],[255,0,148,140],[252,0,151,140],[249,2,121,138],
		[247,3,123,137],[246,3,123,137],[246,2,124,137],[258,2,112,137],[263,2,106,137],[263,2,106,137],[262,2,103,137],
		[260,2,104,136],[260,2,104,137,1],[268,2,98,137],[267,2,99,137],[266,2,97,137],[266,3,96,136],[264,3,99,136],
		[263,3,100,136],[261,3,100,136],[259,2,138,137],[254,2,126,137],[247,2,101,136],[240,2,108,136],[238,1,110,137],
		[230,1,118,138],[220,15,128,124],[211,18,137,121],[205,43,102,96],[202,45,104,93],[200,38,97,101],[198,38,104,101,1],
		[197,39,107,100],[197,39,112,100],[213,39,94,110],[212,40,95,111],[211,41,97,111],[209,42,99,112],[209,43,98,112],
		[213,43,87,112],[213,42,83,113],[211,40,86,109],[211,38,86,103],[211,37,88,112],[211,20,186,131],[213,27,167,122],
		[212,44,87,105],[210,44,88,98],[195,44,106,98],[189,44,110,98],[182,46,117,99],[173,44,118,96,1],[161,43,130,99],
		[154,42,137,97],[153,42,137,97],[153,42,137,97],[152,41,137,98],[151,41,137,97],[149,41,145,97],[148,25,144,114],
		[148,13,144,126],[141,12,153,127],[115,11,173,128],[108,7,180,133],[108,4,180,136],[108,3,176,137,1],[108,1,161,139],
		[105,1,235,138],[103,1,295,148],[103,0,277,149],[108,0,234,137],[101,0,232,137],[99,0,135,139],[95,0,244,139],
		[81,0,152,139],[69,0,164,139,1],[66,0,169,139],[65,0,170,139],[63,0,168,138],[61,0,159,138],[35,0,304,139],[19,0,189,140],
		[18,11,138,129],[18,11,137,129],[18,11,137,128],[18,6,135,133],[7,4,146,136],[6,4,147,136],[3,4,150,136,1],[3,5,150,135],
		[3,8,150,132],[4,6,394,145],[12,6,388,145],[11,8,389,144],[11,8,387,144],[11,8,387,143,1],[10,8,113,131],[11,8,111,131],
		[10,9,112,130],[12,9,116,130],[12,9,111,130],[12,9,111,130],[12,9,110,131],[12,34,113,106],[13,35,110,104]],
		e=d.length,f,g,h,i,j=-1,l=function(){var a=d[f],c=document.getElementById("hplogo");

	if(c&&a[0])
	{
		var b=document.createElement("div");
		b.id="hplogo"+f;
		b.style.left=a[0]+"px";
		b.style.top=a[1]+"px";
		b.style.width=a[2]+"px";
		b.style.height=a[3]+"px";
		b.style.background="url(http://commondatastorage.googleapis.com/blogimgs/graham11-hp-sprite.png) no-repeat "+-g+"px "+-h+"px";
		b.style.border="1px solid #FF0000"; //加上border來觀察每張動畫的更新
		a[3]>i&&(i=a[3]);
		a[4]?(g=0,h+=i,i=0):g+=a[2];
		c.appendChild(b);
		++f;
		f< e&&(j=window.setTimeout(l,183))}},m=function(){
			google.doodle.a=!1;
			i=h=g=f=0;
			j!=-1&&(window.clearTimeout(j),j=-1);
			for(var a=0;a< e;++a)
			{
				var c=document.getElementById("hplogo"+a);
				c&&c.parentNode&&c.parentNode.removeChild(c)
			}
			j=window.setTimeout(l,183)
		};
		if(!google.doodle.a)
		{
			google.doodle.a=!0;
			var n=document.createElement("img");
			n.addEventListener?n.addEventListener("load",m,!1):n.attachEvent("onload",m);
			n.src="http://commondatastorage.googleapis.com/blogimgs/graham11-hp-sprite.png"
		}
	}
	catch(o){google.ml(o,!1,{cause:"DOODLE"})};
	})();

</script>

另外,因為好奇動畫的實際運作方式,所以做了一些修改來觀察:

  1. 把動畫速度調慢來觀察。
  2. 在產生圖片時加上紅邊框,所以可以發現它是一張一張取出後作成div,然後蓋在之前跑出來的動畫上。
  3. 把背景改成黑色,所以可發現png雖不是透明背景,但把它設為div的不重覆背景,也能巧妙的避開後面要留著的圖片。

最後,請見Demo比較原始版與修改版的不同。

上一篇
下一篇

在〈Google Doodle-Google首頁的javascript動畫初探〉中有 9 則留言

  1. 路人甲

    今天的google真的很不一樣,讓人印象深刻,我搜尋了一會才找到作者,謝謝您的分享!

  2. 因為真的很喜歡這次的動畫,所以才花了一些時間研究,謝謝 路人甲 的鼓勵! 🙂

  3. […] 转自:https://audilu.com/2011/05/11/google-doodle-javascript-animation/ […]

  4. 我不知道google首頁有動畫!
    隔天朋友問我可以抓嗎?
    我才搜尋,找到您的網站!
    真是受益良多啊!
    雖然不會javascript,但還是會研究看看的!
    真是謝謝你的解說!

  5. Hi ayuni, 謝謝你的支持!

  6. 您真神耶!
    真的很感謝你的分享!

  7. Hi Jason, 你過獎了,謝謝你的留言 🙂

  8. 你超級厲害的!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料。