使用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 回调函数中变量作用域的讨论
Sep 11 Javascript
在Javascript里访问SharePoint列表数据的实现方法
May 22 Javascript
jQuery表格插件ParamQuery简单使用方法示例
Dec 05 Javascript
JQuery实现防止退格键返回的方法
Feb 12 Javascript
jQuery网页版打砖块小游戏源码分享
Aug 20 Javascript
jquery结合html实现中英文页面切换
Nov 29 Javascript
浅谈Angular2 ng-content 指令在组件中嵌入内容
Aug 18 Javascript
Vue进度条progressbar组件功能
Apr 17 Javascript
Vue.js 实现微信公众号菜单编辑器功能(二)
May 08 Javascript
怎样使你的 JavaScript 代码简单易读(推荐)
Apr 16 Javascript
微信小程序图片右边加两行文字的代码
Apr 23 Javascript
antd vue table跨行合并单元格,并且自定义内容实例
Oct 28 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 内存缓存加速功能memcached安装与用法
2009/09/03 PHP
PHP运行模式的深入理解
2013/06/03 PHP
php实现QQ空间获取当前用户的用户名并生成图片
2015/07/25 PHP
thinkPHP3.2.3实现阿里大于短信验证的方法
2018/06/06 PHP
Array, Array Constructor, for in loop, typeof, instanceOf
2011/09/13 Javascript
javaScript中with函数用法实例分析
2015/06/08 Javascript
jQuery EasyUI实现右键菜单变灰不可用效果
2015/09/24 Javascript
详解JavaScript中数组和字符串的lastIndexOf()方法使用
2016/03/13 Javascript
详解Angular2中的编程对象Observable
2016/09/17 Javascript
JS检测是否可以访问公网服务器功能代码
2017/06/19 Javascript
实例讲解DataTables固定表格宽度(设置横向滚动条)
2017/07/11 Javascript
基于Vue实现页面切换左右滑动效果
2020/06/29 Javascript
微信小程序的日期选择器的实例详解
2017/09/29 Javascript
angular4 JavaScript内存溢出问题
2018/03/06 Javascript
浅谈webpack 四个核心概念之Entry
2019/06/12 Javascript
微信小程序如何调用json数据接口并解析
2019/06/29 Javascript
vue 使用微信jssdk,调用微信相册上传图片功能
2020/11/13 Javascript
python3 pillow生成简单验证码图片的示例
2017/09/19 Python
Python3爬楼梯算法示例
2019/03/04 Python
Django学习笔记之为Model添加Action
2019/04/30 Python
Python全局锁中如何合理运用多线程(多进程)
2019/11/06 Python
Django使用消息提示简单的弹出个对话框实例
2019/11/15 Python
使用Python给头像加上圣诞帽或圣诞老人小图标附源码
2019/12/25 Python
解决python调用自己文件函数/执行函数找不到包问题
2020/06/01 Python
tensorflow dataset.shuffle、dataset.batch、dataset.repeat顺序区别详解
2020/06/03 Python
python抢购软件/插件/脚本附完整源码
2021/03/04 Python
CSS3 实现弹幕的示例代码
2017/08/07 HTML / CSS
英国奢侈品概念店:Base Blu
2019/05/16 全球购物
满月酒答谢词
2014/01/14 职场文书
教学个人的自我评价分享
2014/02/16 职场文书
机关节能减排实施方案
2014/03/17 职场文书
学校领导班子对照检查材料
2014/08/28 职场文书
2015年乡镇统计工作总结
2015/04/22 职场文书
会计岗位工作总结
2015/08/12 职场文书
海贼王十大逆天果实 魂魂果实上榜,岩浆果实攻击力最强
2022/03/18 日漫
一篇文章带你掌握SQLite3基本用法
2022/06/14 数据库