ImagesLazyLoad 圖片延遲載入效果
之前在做一個圖片瀏覽效果時,要看後面的小圖必須等到前面的載入完,而且大圖的位置是在大量的小圖後面,導致大圖要等到小圖都載入完才能顯示,為了解決這個問題,就想到了Lazyload效果。
現在很多網站都用了類似的效果,如淘寶、Bing等。
這個圖片延遲載入效果是在Lazyload的基礎上擴充套件的,主要擴充套件了獲取img元素,獲取src和圖片載入的部分。
相容:ie6/7/8, firefox 3.5.5, opera 10.10, safari 4.0.4, chrome 3.0
其中safari和chrome部分功能不支援。
效果預覽
|
程式說明
【獲取圖片】
先定義filter函式作為篩選程式:
程式碼
然後用這個filter函式篩選出需要的圖片集合:
opt.images || container.getElementsByTagName("img"), filter
);
如果要自定義圖片集合可以在程式可選引數的images屬性來設定,否則自動從容器獲取img元素作為圖片集合。
這裡的filter其實是包裝了篩選樣式cls、獲取src的方法getSrc和佔位圖holder三個引數的_filter篩選程式。
在_filter程式中,會對圖片集合進行篩選和整理。
如果自定義了"class"篩選樣式,會自動排除樣式不對應的圖片:
再用getSrc獲取原圖地址,即實際要顯示的圖片地址。
如果有自定義getSrc會優先使用。
沒有的話,再通過儲存原圖地址的_attribute自定義屬性從元素獲取。
最後才直接從元素的src屬性獲取。
接著排除src不存在的:
要注意處理原圖地址就是元素當前src的情況:
if ( img.complete || $$B.chrome || $$B.safari ) returnfalse;
img.removeAttribute("src");
}
如果complete為true,說明圖片已經載入完成了,可以排除;
如果是chrome或safari,不能取消當前載入,所以也排除掉(具體看圖片的HTTP請求部分)。
否則,用removeAttribute移除src屬性來取消圖片當前的載入。
如果設定了holder佔位圖,就重新設定圖片src:
最後把原圖地址記錄到元素的_attribute自定義屬性中:
逐個圖片元素篩選整理後,就得到要載入的圖片集合了。
【圖片載入】
ImagesLazyLoad相比LazyLoad,已經實現了_onLoadData載入程式,不需要再自己定義載入。
在_onLoadData程式中,主要是用來顯示圖片。
先用_hasAttribute方法判斷是否有_attribute自定義屬性。
在_hasAttribute方法中是這樣判斷的:
?function(img){ return attribute in img; }
: function(img){ return img.hasAttribute( attribute ); };
由於ie6/7跟其他瀏覽器對attribute和property的理解不同,所以要分開處理,詳細參考這裡的attribute/property。
為了保證相容性,程式會優先使用attribute的方式來操作自定義屬性。
當img有_attribute自定義屬性時,就用getAttribute來獲取原圖地址,並設定img的src,在用removeAttribute來移除自定義屬性。
移除的意義在於,當有多個例項使用同一個元素時,能保證圖片載入一次後就不會重複載入,即防止例項間的衝突。
【圖片的HTTP請求】
這裡說說開發過程中發現的一些關於圖片載入的問題。
首先是載入空字串的問題,如果給img的src設為空字串的話,可能會得到意料之外的結果。
例如在 http://xxx/test.htm 裡面的 <img src=""> 會發生以下情況:
ie 會產生相對地址的請求,即:http://xxx/
Safari/Chrome 會產生當前頁面地址的請求,即:http://xxx/test.htm
Opera/Firefox 不會產生請求
詳細參考Nicholas C. Zakas的“Empty image src can destroy your site”。
如果不想載入圖片,不應該把src設為空值,因為還可能會發出請求,浪費資源。
可以像程式那樣,通過removeAttribute來移除就行了。
還有一個問題是在Safari和Chrome,由於webkit核心的bug,正在載入的圖片並不能取消載入。
所以程式在取消圖片載入的部分,如果是Safari或Chrome會繼續載入,不進行延遲。
這個問題最初從lifesinger的datalazyload的說明部分看到的,具體可以自己用Fiddler來測試。
更多相關資料可以參考lifesinger的“圖片的HTTP請求”。
【繼承結構】
在釋出的程式中,這是第一個用了繼承的,本人平時也沒怎麼用到,所以還不成熟,算是試試水吧。
程式用wrapper來做繼承,詳細參考工具庫的說明。
先用wrapper給ImagesLazyLoad包裝(繼承)LazyLoad:
...
}, LazyLoad);
再用extend擴充套件prototype,新增子類的方法函式:
...
});
其中_initialize方法用來設定子類屬性,由於覆蓋了父類的同名方法,所以要通過LazyLoad.prototype._initialize來呼叫,還要注意用call來修正this。
還有_setOptions方法用來設定子類的可選屬性:
...
}, $$.extend( options, {
onLoadData: this._onLoadData
})));
子類的_setOptions方法也覆蓋了父類的方法,解決方法同_initialize。
其中第一個引數是子類的可選屬性,第二個引數是子類定義的屬性,即不再是可選而是由程式來定義的屬性。
總體來說,這是個簡陋的繼承,等以後積累了一定經驗再來擴充套件吧。
使用技巧
【設定src】
有幾個方法可以設定原圖地址:
1,正常設定src:漸進增強,不支援js時也能顯示,但chrome和safari有bug,不支援這種方式;
2,把原圖地址設定到自定義屬性中:所有瀏覽器都相容,但在不支援js時圖片不能顯示;
3,用自定義函式獲取:使用在比較複雜的情況,需要手動設定。
具體還是要根據實際情況來選擇。
【設定holder】
如果使用了holder佔位圖,程式會自動設定圖片元素顯示佔位圖。
推薦使用loading圖片來設定,但loading圖往往跟原圖的尺寸是不同的。
如果img設定了原圖寬高,又想保持loading圖的尺寸,把它設為背景就可以了。
但這樣在ie下,不設定src預設會有一個小圖示。
要去掉這個小圖示可以設定holder為一個透明圖片的連結,或者參考這裡的TRANSPARENT“做”一個透明圖片。
例項中也是這樣設定的,可以參考一下。
【執行程式】
千萬不能在window.onload中執行,因為那時圖片都已經載入完了。
而應該在容器後面(window的話是文件結尾)或DOMContentLoaded中執行。
程式原始碼