DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> ImagesLazyLoad 圖片延遲加載效果
ImagesLazyLoad 圖片延遲加載效果
編輯:關於JavaScript     

網頁制作poluoluo文章簡介:之前在做一個圖片浏覽效果時,要看後面的小圖必須等到前面的加載完,而且大圖的位置是在大量的小圖後面,導致大圖要等到小圖都加載完才能顯示,為了解決這個問題,就想到了Lazyload效果。

之前在做一個圖片浏覽效果時,要看後面的小圖必須等到前面的加載完,而且大圖的位置是在大量的小圖後面,導致大圖要等到小圖都加載完才能顯示,為了解決這個問題,就想到了Lazyload效果。
現在很多網站都用了類似的效果,如淘寶、Bing等。
這個圖片延遲加載效果是在Lazyload的基礎上擴展的,主要擴展了獲取img元素,獲取src和圖片加載的部分。

兼容:ie6/7/8, firefox 3.5.5, opera 10.10, safari 4.0.4, chrome 3.0
其中safari和chrome部分功能不支持。


效果預覽

圖片延遲加載:共有圖片張,未載入 張 photo photo photo photo photo

 

程序說明

【獲取圖片】

先定義filter函數作為篩選程序:

photophoto代碼 var getSrc = opt.getSrc,
filter = $$F.bind( this._filter, this,
opt["class"],
getSrc ? function(img){ return getSrc(img); }
: function(img){ return img.getAttribute( attribute ) || img.src; },
opt.holder
);


然後用這個filter函數篩選出需要的圖片集合:

this._elems = $$A.filter(
opt.images || container.getElementsByTagName("img"), filter
);

如果要自定義圖片集合可以在程序可選參數的images屬性來設置,否則自動從容器獲取img元素作為圖片集合。

這裡的filter其實是包裝了篩選樣式cls、獲取src的方法getSrc和占位圖holder三個參數的_filter篩選程序。
在_filter程序中,會對圖片集合進行篩選和整理。
如果自定義了"class"篩選樣式,會自動排除樣式不對應的圖片:

if ( cls && img.className !== cls ) return false;


再用getSrc獲取原圖地址,即實際要顯示的圖片地址。
如果有自定義getSrc會優先使用。
沒有的話,再通過保存原圖地址的_attribute自定義屬性從元素獲取。
最後才直接從元素的src屬性獲取。

接著排除src不存在的:

if ( !src ) return false;


要注意處理原圖地址就是元素當前src的情況:

if ( src == img.src ) {
if ( img.complete || $$B.chrome || $$B.safari ) return false;
img.removeAttribute("src");
}

如果complete為true,說明圖片已經載入完成了,可以排除;
如果是chrome或safari,不能取消當前加載,所以也排除掉(具體看圖片的HTTP請求部分)。
否則,用removeAttribute移除src屬性來取消圖片當前的加載。

如果設置了holder占位圖,就重新設置圖片src:

if ( holder ) { img.src = holder; }


最後把原圖地址記錄到元素的_attribute自定義屬性中:

img.setAttribute( this._attribute, src );


逐個圖片元素篩選整理後,就得到要加載的圖片集合了。


【圖片加載】

ImagesLazyLoad相比LazyLoad,已經實現了_onLoadData加載程序,不需要再自己定義加載。
在_onLoadData程序中,主要是用來顯示圖片。

先用_hasAttribute方法判斷是否有_attribute自定義屬性。
在_hasAttribute方法中是這樣判斷的:

this._hasAttribute = $$B.ie6 || $$B.ie7
? 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 裡面的  會發生以下情況:
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:

var ImagesLazyLoad = $$.wrapper(function(options) {
...
}, LazyLoad);


再用extend擴展prototype,添加子類的方法函數:

$$.extend( ImagesLazyLoad.prototype, {
...
});


其中_initialize方法用來設置子類屬性,由於覆蓋了父類的同名方法,所以要通過LazyLoad.prototype._initialize來調用,還要注意用call來修正this。

還有_setOptions方法用來設置子類的可選屬性:

return LazyLoad.prototype._setOptions.call(this, $$.extend({
...
}, $$.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中執行。


程序源碼

photophoto代碼 var ImagesLazyLoad = $$.wrapper(function(options) {
this._initialize( options );
//如果沒有元素就退出
if ( this.isFinish() ) return;
//初始化模式設置
this._initMode();
//進行第一次觸發
this.resize(true);
}, LazyLoad);

$$.extend( ImagesLazyLoad.prototype, {
//初始化程序
_initialize: function(options) {
LazyLoad.prototype._initialize.call(this, [], options);
//設置子類屬性
var opt = this.options;
this.onLoad = opt.onLoad;
var attribute = this._attribute = opt.attribute;
//設置加載圖片集合
var getSrc = opt.getSrc,
filter = $$F.bind( this._filter, this,
opt["class"],
getSrc ? function(img){ return getSrc(img); }
: function(img){ return img.getAttribute( attribute ) || img.src; },
opt.holder
);
this._elems = $$A.filter(
opt.images || this._container.getElementsByTagName("img"), filter
);
//判斷屬性是否已經加載的方法
this._hasAttribute = $$B.ie6 || $$B.ie7
? function(img){ return attribute in img; }
: function(img){ return img.hasAttribute( attribute ); };
},
//設置默認屬性
_setOptions: function(options) {
return LazyLoad.prototype._setOptions.call(this, $$.extend({//默認值
images: undefined,//圖片集合
attribute: "_lazysrc",//保存原圖地址的自定義屬性
holder: "",//占位圖
"class": "",//篩選樣式
getSrc: undefined,//獲取原圖地址程序
onLoad: function(){}//加載時執行
}, $$.extend( options, {
onLoadData: this._onLoadData
})));
},
//篩選整理圖片對象
_filter: function(cls, getSrc, holder, img) {
if ( cls && img.className !== cls ) return false;//排除樣式不對應的
//獲取原圖地址
var src = getSrc(img);
if ( !src ) return false;//排除src不存在的
if ( src == img.src ) {
//排除已經加載或不能停止加載的
if ( img.complete || $$B.chrome || $$B.safari ) return false;
img.removeAttribute("src");//移除src
}
if ( holder ) { img.src = holder; }
//用自定義屬性記錄原圖地址
img.setAttribute( this._attribute, src );
return true;
},
//顯示圖片
_onLoadData: function(img) {
var attribute = this._attribute;
if ( this._hasAttribute( img ) ) {
img.src = img.getAttribute( attribute );
img.removeAttribute( attribute );
this.onLoad( img );
}
}
});

 

完整實例下載

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved