使用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 GUID生成器实现代码
Oct 31 Javascript
jquery 选项卡效果 新手代码
Jul 08 Javascript
js indexOf()定义和用法
Oct 21 Javascript
js局部刷新页面时间具体实现
Jul 04 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
Oct 11 Javascript
js实现背景图片感应鼠标变化的方法
Feb 28 Javascript
js弹出窗口返回值的简单实例
May 28 Javascript
js实现精确到秒的倒计时效果
May 29 Javascript
jQuery基本过滤选择器用法示例
Sep 09 Javascript
手机浏览器 后退按钮强制刷新页面方法总结
Oct 09 Javascript
vue 运用mock数据的示例代码
Nov 07 Javascript
vue 自定义 select内置组件
Apr 10 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
php GeoIP的使用教程
2011/03/09 PHP
PHP程序员常见的40个陋习,你中了几个?
2014/11/20 PHP
TP5(thinkPHP5)框架使用ajax实现与后台数据交互的方法小结
2020/02/10 PHP
javascript之dhDataGrid Ver2.0.0代码
2007/07/01 Javascript
js 输出内容到新窗口具体实现代码
2013/05/31 Javascript
一个JS的日期格式化算法示例
2013/07/31 Javascript
jQuery实现页面内锚点平滑跳转特效的方法总结
2015/05/11 Javascript
牛叉的Jquery——Jquery与DOM对象的互相转换及DOM的三种操作
2015/10/29 Javascript
jQuery实现ajax调用WCF服务的方法(附带demo下载)
2015/12/04 Javascript
AngularJS基础 ng-if 指令用法
2016/08/01 Javascript
bootstrap表格分页实例讲解
2016/12/30 Javascript
jquery实现弹窗功能(窗口居中显示)
2017/02/27 Javascript
JSON与js对象序列化实例详解
2017/03/16 Javascript
nodejs express配置自签名https服务器的方法
2018/05/22 NodeJs
Vue项目服务器部署之子目录部署方法
2019/05/12 Javascript
vue data引入本地图片的两种方式小结
2019/11/13 Javascript
Vue+ElementUI使用vue-pdf实现预览功能
2019/11/26 Javascript
如何在微信小程序中存setStorage
2019/12/13 Javascript
JS实现网站吸顶条
2020/01/08 Javascript
对Python进行数据分析_关于Package的安装问题
2017/05/22 Python
解决pandas使用read_csv()读取文件遇到的问题
2018/06/15 Python
用python统计代码行的示例(包括空行和注释)
2018/07/24 Python
Python3中在Anaconda环境下安装basemap包
2018/10/21 Python
python对于requests的封装方法详解
2019/01/03 Python
Python分支语句与循环语句应用实例分析
2019/05/07 Python
美国益智玩具购物网站:Fat Brain Toys
2017/11/03 全球购物
Gina Bacconi官网:吉娜贝康尼连衣裙和礼服
2018/04/24 全球购物
美国眼镜网站:LensCrafters
2020/01/19 全球购物
银行实习鉴定
2013/12/13 职场文书
小学生演讲稿
2014/01/12 职场文书
应聘教师自荐书
2014/06/16 职场文书
女生抽烟检讨书
2014/10/05 职场文书
物价局领导班子四风问题整改措施
2014/10/26 职场文书
毕业论文指导教师评语
2014/12/30 职场文书
职代会闭幕词
2015/01/28 职场文书
新手入门Mysql--sql执行过程
2021/06/20 MySQL