使用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语言的思想前提想学习js的朋友可以看看
Apr 01 Javascript
Jquery 学习笔记(一)
Oct 13 Javascript
jquery获得下拉框值的代码
Aug 13 Javascript
jQuery EasyUI API 中文文档 - TimeSpinner时间微调器
Oct 23 Javascript
通过Javascript将数据导出到外部Excel文档的函数代码
Jun 15 Javascript
JS获取select-option-text_value的方法
Dec 26 Javascript
js如何实现淡入淡出效果
Nov 18 Javascript
JavaScript中的this,call,apply使用及区别详解
Jan 29 Javascript
jQuery+ajax实现实用的点赞插件代码
Jul 06 Javascript
微信小程序对接七牛云存储的方法
Jul 30 Javascript
mpvue 单文件页面配置详解
Dec 02 Javascript
vue父子模板传值问题解决方法案例分析
Feb 26 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
评分9.0以上的动画电影,剧情除了经典还很燃
2020/03/04 日漫
PHP学习 变量使用总结
2011/03/24 PHP
php排序算法(冒泡排序,快速排序)
2012/10/09 PHP
深入解析PHP垃圾回收机制对内存泄露的处理
2013/06/14 PHP
TFDN图片播放器 不错自动播放
2006/10/03 Javascript
jquery文字上下滚动的实现方法
2013/03/22 Javascript
JS实现的最简Table选项卡效果
2015/10/14 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
基于jQuery实现照片墙自动播放特效
2017/01/12 Javascript
canvas绘图不清晰的解决方案
2017/02/28 Javascript
JavaScript实现类似淘宝的购物车效果
2017/03/16 Javascript
vue 怎么创建组件及组件使用方法
2017/07/27 Javascript
js如何获取图片url的Blob值并预览示例代码
2019/03/07 Javascript
微信小程序学习笔记之登录API与获取用户信息操作图文详解
2019/03/29 Javascript
JavaScript中的全局属性与方法深入解析
2020/06/14 Javascript
vue实现图片上传到后台
2020/06/29 Javascript
Python使用CMD模块更优雅的运行脚本
2015/05/11 Python
将Python代码嵌入C++程序进行编写的实例
2015/07/31 Python
python获取list下标及其值的简单方法
2016/09/12 Python
pygame实现弹力球及其变速效果
2017/07/03 Python
python在TXT文件中按照某一字符串取出该字符串所在的行方法
2018/12/10 Python
在python中pandas读文件,有中文字符的方法
2018/12/12 Python
python读取目录下最新的文件夹方法
2018/12/24 Python
Python实现二维曲线拟合的方法
2018/12/29 Python
PyQt弹出式对话框的常用方法及标准按钮类型
2019/02/27 Python
HTML5页面无缝闪开的问题及解决方案
2020/06/11 HTML / CSS
P D PAOLA意大利官网:西班牙著名的珠宝首饰品牌
2019/09/24 全球购物
招聘与培训专员岗位职责
2014/01/30 职场文书
个人实习生的自我评价
2014/02/16 职场文书
党的群众路线教育实践活动方案
2014/10/31 职场文书
小学教师岗位职责
2015/04/02 职场文书
离婚被告答辩状
2015/05/22 职场文书
肖申克的救赎观后感
2015/06/02 职场文书
2016年优秀班主任先进事迹材料
2016/02/26 职场文书
sql字段解析器的实现示例
2021/06/23 SQL Server
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记