使用jquery实现的一个图片延迟加载插件(含图片延迟加载原理)


Posted in Javascript onJune 05, 2014

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

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

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

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

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

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

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

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

(function( $ ){
$.fn.imglazyload = function( options ){
 var o = $.extend({
    attr  :   'lazy-src', 
    container  :  window, 
    event   :  'scroll',    
    fadeIn      :   false,    
    threshold  :  0, 
    vertical  :  true 
   }, options ),
  event = o.event,
  vertical = o.vertical,
  container = $( o.container ),
  threshold = o.threshold, 
  // 将jQuery对象转换成DOM数组便于操作
  elems = $.makeArray( $(this) ),  
  dataName = 'imglazyload_offset',   
  OFFSET = vertical ? 'top' : 'left',
  SCROLL = vertical ? 'scrollTop' : 'scrollLeft',   
  winSize = vertical ? container.height() : container.width(),
  scrollCoord = container[ SCROLL ](),
  docSize = winSize + scrollCoord;
 // 延迟加载的触发器 
 var trigger = {
  init : function( coord ){
   return coord >= scrollCoord && 
                            coord <= ( docSize + threshold );
  },
  scroll : function( coord ){
   var scrollCoord = container[ SCROLL ]();
   return coord >= scrollCoord && 
                    coord <= ( winSize + scrollCoord + threshold );
  },
  resize : function( coord ){
   var scrollCoord = container[ SCROLL ](),
    winSize = vertical ? 
                            container.height() : 
                            container.width();
   return coord >= scrollCoord &&
                   coord <= ( winSize + scrollCoord + threshold );
  }
 };
 var loader = function( triggerElem, event ){
  var i = 0,
   isCustom = false,
   isTrigger, coord, elem, $elem, lazySrc;
  // 自定义事件只要触发即可,无需再判断
  if( event ){
   if( event !== 'scroll' && event !== 'resize' ){
    isCustom = true;
   }
  }
  else{
   event = 'init';
  }
  for( ; i < elems.length; i++ ){ 
   isTrigger = false;
   elem = elems[i];
   $elem = $( elem );
   lazySrc = $elem.attr( o.attr );
   if( !lazySrc || elem.src === lazySrc ){
    continue;
   }
   // 先从缓存获取offset值,缓存中没有才获取计算值,
   // 将计算值缓存,避免重复获取引起的reflow
   coord = $elem.data( dataName );
   if( coord === undefined ){
    coord = $elem.offset()[ OFFSET ];
    $elem.data( dataName, coord );
   }
   isTrigger = isCustom || trigger[ event ]( coord );   
   if( isTrigger ){
    // 加载图片
    elem.src = lazySrc;
    if( o.fadeIn ){
     $elem.hide().fadeIn();
    }
    // 移除缓存
    $elem.removeData( dataName );
    // 从DOM数组中移除该DOM
    elems.splice( i--, 1 );
   }
  }
  // 所有的图片加载完后卸载触发事件
  if( !elems.length ){
   if( triggerElem ){
    triggerElem.unbind( event, fire );
   }
   else{
    container.unbind( o.event, fire );
   }
   $( window ).unbind( 'resize', fire );
   elems = null;
  }
 };
 var fire = function( e ){
  loader( $(this), e.type );
 };
 // 绑定事件
 container = event === 'scroll' ? container : $( this ); 
 container.bind( event, fire );
 $( window ).bind( 'resize', fire );
 // 初始化
 loader();
 return this;
};
})( jQuery );

调用:

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

默认的调用可以省略所有参数。
$( '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。

Javascript 相关文章推荐
javascript之卸载鼠标事件的代码
May 14 Javascript
XRegExp 0.2: Now With Named Capture
Nov 30 Javascript
jquery 如何动态添加、删除class样式方法介绍
Nov 07 Javascript
Javascript基础教程之关键字和保留字汇总
Jan 18 Javascript
javascript继承的六大模式小结
Apr 13 Javascript
js实现简单的联动菜单效果
Aug 19 Javascript
javascript下使用Promise封装FileReader
Feb 19 Javascript
jQuery遍历DOM元素与节点方法详解
Apr 14 Javascript
JavaScript中闭包之浅析解读(必看篇)
Aug 25 Javascript
Jquery实时监听input value的实例
Jan 26 Javascript
vue中使用better-scroll实现滑动效果及注意事项
Nov 15 Javascript
JS forEach跳出循环2种实现方法
Jun 24 Javascript
用js的document.write输出的广告无阻塞加载的方法
Jun 05 #Javascript
javascript数组去重方法终极总结
Jun 05 #Javascript
javascript设计模式之解释器模式详解
Jun 05 #Javascript
javascript监听鼠标滚轮事件浅析
Jun 05 #Javascript
详解JavaScript语法对{}处理的坑爹之处
Jun 05 #Javascript
封装了一个支持匿名函数的Javascript事件监听器
Jun 05 #Javascript
用js读、写、删除Cookie代码分享及详细注释说明
Jun 05 #Javascript
You might like
asp和php下textarea提交大量数据发生丢失的解决方法
2008/01/20 PHP
Sorting Array Values in PHP(数组排序)
2011/09/15 PHP
PHP基础知识回顾
2012/08/16 PHP
Mysql中分页查询的两个解决方法比较
2013/05/02 PHP
[原创]PHP获取数组表示的路径方法分析【数组转字符串】
2017/09/01 PHP
用jscript实现新建word文档
2007/06/15 Javascript
从jQuery.camelCase()学习string.replace() 函数学习
2011/09/13 Javascript
jQuery实现的一个自定义Placeholder属性插件
2014/08/11 Javascript
jquery模拟alert的弹窗插件
2015/07/31 Javascript
表单验证插件Validation应用的实例讲解
2015/10/10 Javascript
总结十个Angular.js由浅入深的面试问题
2016/08/26 Javascript
Node.js中常规的文件操作总结
2016/10/13 Javascript
详解angularjs中的隔离作用域理解以及绑定策略
2017/05/31 Javascript
基于Vue实现拖拽功能
2020/07/29 Javascript
vue自定义一个v-model的实现代码
2018/06/21 Javascript
微信小程序登录session的使用
2019/03/17 Javascript
Flutter实现仿微信底部菜单栏功能
2019/09/18 Javascript
python中的代码编码格式转换问题
2015/06/10 Python
使用Python实现windows下的抓包与解析
2018/01/15 Python
python 删除非空文件夹的实例
2018/04/26 Python
python生成ppt的方法
2018/06/07 Python
Python 常用模块 re 使用方法详解
2019/06/06 Python
Python字典对象实现原理详解
2019/07/01 Python
在Python中os.fork()产生子进程的例子
2019/08/08 Python
解决python彩色螺旋线绘制引发的问题
2019/11/23 Python
python实现人机猜拳小游戏
2020/02/03 Python
解决Python数据可视化中文部分显示方块问题
2020/05/16 Python
Python数据相关系数矩阵和热力图轻松实现教程
2020/06/16 Python
Python爬虫UA伪装爬取的实例讲解
2021/02/19 Python
处理HTML5新标签的浏览器兼容版问题
2017/03/13 HTML / CSS
Vilebrequin美国官方网上商店:法国豪华泳装品牌
2020/02/22 全球购物
Myprotein荷兰官网:欧洲第一运动营养品牌
2020/07/11 全球购物
会计专业自荐信
2013/12/02 职场文书
2013年军训通讯稿
2014/02/05 职场文书
自强自立美德少年事迹材料
2014/08/16 职场文书
党员评议表自我评价范文
2014/10/20 职场文书