图片延迟加载的实现

图片延迟加载也称懒加载,通常应用于图片比较多的网页,如果一个页面图片比较多,且页面高度或宽度有好几屏,页面初次加载时,只显示可视区域的图 片,当页面滚动的时候,图片进入了可视区域再进行加载,这样可以显著的提高页面的加载速度,更少的图片并发请求数也可以减轻服务器的压力。如果用户仅仅在 首屏停留,还可以节省流量。如果TAB中的图片较多,也同样可以应用于TAB中,当触发TAB时再进行图片的加载。

图片延迟加载的原理比较简单,先将图片的真实地址缓存在一个自定义的属性(lazy-src)中,而src地址使用一个1×1的全透明的占位图片来代替,当然占位图片也可以是其他的图片。

1 <img src="images/placeholder.png"  lazy-src="images/realimg.jpg" />

因为是使用javascript来加载图片,如果用户禁用了javascript,可以设置一个替代的方案。

1 <img src="images/placeholder.png"  lazy-src="images/realimg.jpg" alt="" />
2 <noscript><img src="images/realimg.jpg"  alt="" /></noscript>

页面初次加载时获取图片在页面中的位置并缓存(每次取offset的值会引发页面的reflow),计算出可视区域,当图片的位置出现在可视区域中,将src的值替换成真实的地址,此时图片就开始加载了。

当页面滚动的时候,再判断图片已经缓存的位置值是否出现在可视区域内,进行替换src加载。当所有的图片都加载完之后,将相应的触发事件卸载,避免 重复操作引起的内存泄漏。将整个窗口看成是一个大容器,那么也可以在页面中设置一个小容器,在小容器中也同样可以实现图片的延迟加载。

下面是实现的代码,我写成了jQuery插件。

001 (function( $ ){
002 $.fn.imglazyload = function( options ){
003     var o = $.extend({
004                 attr        :   'lazy-src',
005                 container   :   window,
006                 event       :   'scroll',
007                 fadeIn      :   false,
008                 threshold   :   0,
009                 vertical    :   true
010             }, options ),
011  
012         event = o.event,
013         vertical = o.vertical,
014         container = $( o.container ),
015         threshold = o.threshold,
016         // 将jQuery对象转换成DOM数组便于操作
017         elems = $.makeArray( $(this) ),
018         dataName = 'imglazyload_offset',
019         OFFSET = vertical ? 'top' 'left',
020         SCROLL = vertical ? 'scrollTop' 'scrollLeft',
021         winSize = vertical ? container.height() : container.width(),
022         scrollCoord = container[ SCROLL ](),
023         docSize = winSize + scrollCoord;
024  
025     // 延迟加载的触发器
026     var trigger = {
027  
028         init : function( coord ){
029             return coord >= scrollCoord &&
030                             coord <= ( docSize + threshold );
031         },
032  
033         scroll : function( coord ){
034             var scrollCoord = container[ SCROLL ]();
035             return coord >= scrollCoord &&
036                     coord <= ( winSize + scrollCoord + threshold );
037         },
038  
039         resize : function( coord ){
040             var scrollCoord = container[ SCROLL ](),
041                 winSize = vertical ?
042                             container.height() :
043                             container.width();
044             return coord >= scrollCoord &&
045                    coord <= ( winSize + scrollCoord + threshold );
046         }
047     };
048  
049     var loader = function( triggerElem, event ){
050         var i = 0,
051             isCustom = false,
052             isTrigger, coord, elem, $elem, lazySrc;
053  
054         // 自定义事件只要触发即可,无需再判断
055         ifevent ){
056             ifevent !== 'scroll' && event !== 'resize' ){
057                 isCustom = true;
058             }
059         }
060         else{
061             event 'init';
062         }
063  
064         for( ; i < elems.length; i++ ){
065             isTrigger = false;
066             elem = elems[i];
067             $elem = $( elem );
068             lazySrc = $elem.attr( o.attr );
069  
070             if( !lazySrc || elem.src === lazySrc ){
071                 continue;
072             }
073             // 先从缓存获取offset值,缓存中没有才获取计算值,
074             // 将计算值缓存,避免重复获取引起的reflow
075             coord = $elem.data( dataName );
076  
077             if( coord === undefined ){
078                 coord = $elem.offset()[ OFFSET ];
079                 $elem.data( dataName, coord );
080             }
081  
082             isTrigger = isCustom || trigger[ event ]( coord );         
083  
084             if( isTrigger ){
085                 // 加载图片
086                 elem.src = lazySrc;
087                 if( o.fadeIn ){
088                     $elem.hide().fadeIn();
089                 }
090                 // 移除缓存
091                 $elem.removeData( dataName );
092                 // 从DOM数组中移除该DOM
093                 elems.splice( i--, 1 );
094             }
095         }
096  
097         // 所有的图片加载完后卸载触发事件
098         if( !elems.length ){
099             if( triggerElem ){
100                 triggerElem.unbind( event, fire );
101             }
102             else{
103                 container.unbind( o.event, fire );
104             }
105             $( window ).unbind( 'resize', fire );
106             elems = null;
107         }
108  
109     };
110  
111     var fire = function( e ){
112         loader( $(this), e.type );
113     };
114  
115     // 绑定事件
116     container = event === 'scroll' ? container : $( this );
117     container.bind( event, fire );
118     $( window ).bind( 'resize', fire );
119  
120     // 初始化
121     loader();
122  
123     return this;
124 };
125  
  })( jQuery );

调用:

  $( 'img' ).imglazyload({
      event 'scroll',
      attr : 'lazy-src'
4 });

默认的调用可以省略所有参数。

  $( 'img' ).imglazyload();

图片延迟加载的插件API说明:

  • attr string
  • 存放图片真实地址的属性名,与HTML对应,默认是lazy-src。
  • container dom & selector
  • 默认的容器为window,可自定义容器。
  • event stirng
  • 触发图片加载的事件类型,默认为window.onscroll事件
  • fadeIn boolean
  • 是否使用jQuery的fadeIn效果来显示,默认是false。
  • threshold number
  • 页面滚动到离图片还有指定距离的时候就进行加载,默认是0。
  • vertical boolean
  • 是否横向滚动,默认为true(纵向)。
  • loadScript(增强版的功能) boolean
  • 是否无阻塞加载javascript广告图片,默认为false。

 

http://blog.163.com/wolfers@126/blog/static/1630236942012435142224/

posted @ 2013-08-12 13:56  小小的我$  阅读(161)  评论(0编辑  收藏  举报