ImagesLazyLoad 图片延迟加载效果

it2025-03-24  13

之前在做一个图片浏览效果时,要看后面的小图必须等到前面的加载完,而且大图的位置是在大量的小图后面,导致大图要等到小图都加载完才能显示,为了解决这个问题,就想到了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函数作为筛选程序:

代码 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  ( className  &&  ( "   "   +  img.className  +   "   " ).indexOf( "   "   +  className  +   "   " ==   - 1  )  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 里面的 <img src=""> 会发生以下情况:ie 会产生相对地址的请求,即:http://xxx/Safari/Chrome 会产生当前页面地址的请求,即:http://xxx/test.htmOpera/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中执行。

程序源码 

代码 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 );    }  }});

 

完整实例下载

转载于:https://www.cnblogs.com/cloudgamer/archive/2010/03/03/ImagesLazyLoad.html

相关资源:数据结构—成绩单生成器
最新回复(0)