使用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 相关文章推荐
为数据添加append,remove功能
Oct 03 Javascript
(currentStyle)javascript为何有时用style得不到已设定的CSS的属性
Aug 15 Javascript
jquery 表单进行客户端验证demo
Aug 24 Javascript
ASP.NET中AJAX 调用实例代码
May 03 Javascript
jquery ajax中使用jsonp的限制解决方法
Nov 22 Javascript
Javascript中的delete操作符详细介绍
Jun 06 Javascript
javascript 构造函数方式定义对象
Jan 02 Javascript
基于JavaScript将表单序列化类型的数据转化成对象的处理(允许对象中包含对象)
Dec 28 Javascript
微信jssdk用法汇总
Jul 16 Javascript
vue实现条件判断动态绑定样式的方法
Sep 29 Javascript
在微信小程序中使用vant的方法
Jun 07 Javascript
elementui之el-tebs浏览器卡死的问题和使用报错未注册问题
Jul 06 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
海贼王:最美的悬赏令!
2020/03/02 日漫
为什么《星际争霸》是测试人工智能的理想战场
2019/12/03 星际争霸
抓取并下载CSS中所有图片文件的php代码
2011/09/26 PHP
thinkphp使用phpmailer发送邮件的方法
2014/11/24 PHP
Laravel中使用阿里云OSS Composer包分享
2015/02/10 PHP
PHP支付系统设计与典型案例分享
2016/08/02 PHP
在laravel中实现将查询的对象转换为多维数组的函数
2019/10/21 PHP
让mayfish支持mysqli数据库驱动的实现方法
2010/05/22 Javascript
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
2012/02/03 Javascript
JS中批量给元素绑定事件过程中的相关问题使用闭包解决
2013/04/15 Javascript
javaScript年份下拉列表框内容为当前年份及前后50年
2014/05/28 Javascript
JS生成某个范围的随机数【四种情况详解】
2016/04/20 Javascript
javascript实现图片左右滚动效果【可自动滚动,有左右按钮】
2016/09/19 Javascript
jQuery模拟实现的select点击选择效果【附demo源码下载】
2016/11/09 Javascript
浅谈jQuery中事情的动态绑定
2017/02/12 Javascript
JS对象与JSON互转换、New Function()、 forEach()、DOM事件流等js开发基础小结
2017/08/10 Javascript
面包屑导航详解
2017/12/07 Javascript
node中的密码安全(加密)
2018/09/17 Javascript
vue实现手机端省市区区域选择
2019/09/27 Javascript
javascript实现拼图游戏
2021/01/29 Javascript
浅谈python中np.array的shape( ,)与( ,1)的区别
2018/06/04 Python
Flask之flask-script模块使用
2018/07/26 Python
彻彻底底地理解Python中的编码问题
2018/10/15 Python
python下的opencv画矩形和文字注释的实现方法
2019/07/09 Python
python读取与处理netcdf数据方式
2020/02/14 Python
美国批发零售网站:GearXS
2016/07/26 全球购物
Lacoste美国官网:经典POLO衫品牌
2016/10/12 全球购物
波兰电子产品购物网站:Vobis
2019/05/26 全球购物
办公室内勤岗位职责范本
2013/12/09 职场文书
服装设计行业个人的自我评价
2013/12/20 职场文书
博士学位自我鉴定范文
2013/12/26 职场文书
中考冲刺决心书
2014/03/11 职场文书
贯彻落实“八项规定”思想汇报
2014/09/13 职场文书
工作迟到检讨书范文
2015/05/06 职场文书
七一晚会主持词
2015/06/29 职场文书
用python批量解压带密码的压缩包
2021/05/31 Python