使用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 相关文章推荐
Ajax执行顺序流程及回调问题分析
Dec 10 Javascript
JS实现的仿淘宝交易倒计时效果
Nov 27 Javascript
Ubuntu 16.04 64位中搭建Node.js开发环境教程
Oct 19 Javascript
JS动态给对象添加属性和值的实现方法
Oct 21 Javascript
详解JS中的快速排序与冒泡
Jan 10 Javascript
jQuery获取复选框选中的当前行的某个字段的值
Sep 15 jQuery
javaScript实现游戏倒计时功能
Nov 17 Javascript
jQuery-ui插件sortable实现自由拖动排序
Dec 01 jQuery
js实现旋转的星空效果
Nov 01 Javascript
JS实现水平移动与垂直移动动画
Dec 19 Javascript
js点击事件的执行过程实例分析【冒泡与捕获】
Apr 11 Javascript
vue-socket.io接收不到数据问题的解决方法
May 13 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 获取本机外网/公网IP的代码
2010/05/09 PHP
PHP读取xml方法介绍
2013/01/12 PHP
解析php5配置使用pdo
2013/07/03 PHP
PHP结合jQuery.autocomplete插件实现输入自动完成提示的功能
2015/04/27 PHP
PHP实现过滤各种HTML标签
2015/05/17 PHP
tp5(thinkPHP5)框架数据库Db增删改查常见操作总结
2019/01/10 PHP
一份老外写的XMLHttpRequest代码多浏览器支持兼容性
2007/01/11 Javascript
又一个图片自动缩小的JS代码
2007/03/10 Javascript
Javascript 兼容firefox的一些问题
2009/05/21 Javascript
精通Javascript系列之Javascript基础篇
2011/06/07 Javascript
JQUERY 实现窗口滚动搜索框停靠效果(类似滚动停靠)
2013/03/27 Javascript
JavaScript实现继承的4种方法总结
2014/10/16 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
基于jQuery实现滚动刷新效果
2017/01/09 Javascript
Bootstrap页面缩小变形的快速解决办法
2017/02/03 Javascript
简单了解vue.js数组的常用操作
2019/06/17 Javascript
[00:47]TI7不朽珍藏III——沙王不朽展示
2017/07/15 DOTA
Python Tkinter简单布局实例教程
2014/09/03 Python
python中Flask框架简单入门实例
2015/03/21 Python
举例详解Python中循环语句的嵌套使用
2015/05/14 Python
深入浅析python继承问题
2016/05/29 Python
python 性能优化方法小结
2017/03/31 Python
PyChar学习教程之自定义文件与代码模板详解
2017/07/17 Python
Python中协程用法代码详解
2018/02/10 Python
Python实现删除时保留特定文件夹和文件的示例
2018/04/27 Python
解决PySide+Python子线程更新UI线程的问题
2019/01/11 Python
Python变量、数据类型、数据类型转换相关函数用法实例详解
2020/01/09 Python
如何使用repr调试python程序
2020/02/28 Python
HTML5边玩边学(1)画布实现方法
2010/09/21 HTML / CSS
ALDO加拿大官网:加拿大女鞋品牌
2018/12/22 全球购物
关键字throw与throws的用法差异
2016/11/22 面试题
会计自我鉴定范文
2013/10/06 职场文书
机械专业毕业生推荐信范文
2013/11/25 职场文书
招聘与培训专员岗位职责
2014/01/30 职场文书
《伯牙绝弦》教学反思
2014/03/02 职场文书
个人维稳承诺书
2015/05/04 职场文书