• 图片延迟加载的实现


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

  • 相关阅读:
    理解js中的原型链,prototype与__proto__的关系
    Zepto源码(2016)——Zepto模块(核心模块)
    MySQL增删改查
    ACM典型试题--古代密码(二)
    ACM典型试题--简单的加密算法(一)
    MySQL图文安装配置
    (c语言)二叉树中序线索(数据结构十七)
    (C语言)二叉树层次遍历(数据结构十六)
    Java连接db2数据库(常用数据库连接五)
    java连接oracle数据库(常用数据库连接四)
  • 原文地址:https://www.cnblogs.com/qqyuhaitao/p/3252792.html
走看看 - 开发者的网上家园