2011年5月11日,google為了紀念現代舞先驅瑪莎·葛蘭姆 117 周年誕辰,用巧妙的技術和奇特的創意在首頁建立了一副跳舞的圖,我把整個源碼下載下傳下來并加以分析和重構,效果圖如下:
整個動畫實際上是由155張小圖檔做出來的(google的設計師太nb了),就像放電影那樣,如下圖:
雖然原理很簡單,就是用js來控制播放上面的圖檔,不過裡面還有很多技巧是值得學習的,下面是我對代碼的分析。
html部分很簡單,就一個div容器:
<div id="hplogo">
<a href="#">
<img title="現代舞先驅瑪莎·葛蘭姆 117 周年誕辰" border="0" alt="現代舞先驅瑪莎·葛蘭姆 117 周年誕辰" src="images/graham11-hp-start.png" />
</a>
</div>
css部分:
#hplogo { position: relative; cursor: pointer; width: 403px; height: 156px; margin: 120px auto 0 auto; background: #fff none repeat 0% 0% scroll; }
#hplogo div { position: absolute; }
js部分(完整代碼在附件中):
(function() {
try {
//二維數組定義155張圖檔的資訊,分别是[圖檔的left, top, width, height, 1(标記,部分數組有)]
//數組中最後一個值“1”是一個标記,表示圖檔換行
var arrimg = [[307, 48, 88, 89], [307, 48, 89, 89], [307, 48, 91, 89]...(省略n個數組)],
imglen = arrimg.length, //圖檔數組長度
imgindex, imgleft, imgtop, maxheight, //分别代表 目前圖檔序号,background-position中的left, top,一行圖檔中的最大高度
fun = -1, //後面settimeout的傳回值,做标記,後面用到
funimgclick = function() { //點選圖檔的事件(跳轉到google搜尋頁面)
google.nav && google.nav.go ?
google.nav.go("/search?q=%e7%8e%9b%e8%8e%8e%c2%b7%e8%91%9b%e5%85%b0%e5%a7%86&ct=graham11-hp&oi=ddle&hl=zh-cn") :
window.location.href = "/search?q=%e7%8e%9b%e8%8e%8e%c2%b7%e8%91%9b%e5%85%b0%e5%a7%86&ct=graham11-hp&oi=ddle&hl=zh-cn"
},
funmakeanimate = function() { //建立并執行動畫的方法,每83毫秒調用一次,建立一個div并設定屬性、背景圖
//取出目前圖檔資訊
var img = arrimg[imgindex],
//所有div都添加到這個容器
wrap = document.getelementbyid("hplogo");
if (wrap && img[0]) {
//開始建立div
var div = document.createelement("div");
div.id = "hplogo" + imgindex;
div.style.left = img[0] + "px";
div.style.top = img[1] + "px";
div.style.width = img[2] + "px";
div.style.height = img[3] + "px";
div.style.background = "url(images/graham11-hp-sprite.png) no-repeat " + -imgleft + "px " + -imgtop + "px";
div.
//這裡使用了利用&&運算符的技巧,下面還會用到這個技巧
//相當于"if (img[3] > maxheight) { maxheight = img[3]; }"
img[3] > maxheight && (maxheight = img[3]); //保證maxheight取目前行最大的圖檔高度
//如果有5個值,則說明換行了,left重新從0開始,并累加top,行最大高度清0
//否則left累加目前圖檔的寬度
img[4] ? (imgleft = 0, imgtop += maxheight, maxheight = 0) : imgleft += img[2];
wrap.appendchild(div);
++imgindex;
//繼續動畫
imgindex < imglen && (fun = window.settimeout(funmakeanimate, 83)); //又是 && ,同上
}
funinit = function() { //頁面加載的時候就執行該函數,初始化變量并調用動畫函數
maxheight = imgtop = imgleft = imgindex = 0;
//如果動畫已經在播放,則先停止并删掉相應的div節點
//再次出現 && 的使用
fun != -1 && (window.cleartimeout(fun), fun = -1);
//删除已經添加的dom節點
for (var index = 0; index < imglen; ++index) {
var div = document.getelementbyid("hplogo" + index);
div && div.parentnode && div.parentnode.removechild(div);
//第一次調用動畫函數
fun = window.settimeout(funmakeanimate, 83);
};
var originimg = document.createelement("img");
//頁面
originimg.addeventlistener ?
originimg.addeventlistener("load", funinit, false) : //addeventlistener用于mozilla系列浏覽器,第三個參數usercapture若為true,則浏覽器采用capture,若為false則采用bubbing方式
originimg.attachevent("onload", funinit); //用于ie浏覽器
originimg.src = "images/graham11-hp-sprite.png";
}
catch (o) {
//google的錯誤處理
//google.ml(o, !1, { cause: "doodle" });
})()