使用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 相关文章推荐
使用Modello编写JavaScript类
Dec 22 Javascript
JS写的数字拼图小游戏代码[学习参考]
Oct 29 Javascript
js 控制页面跳转的5种方法
Sep 09 Javascript
js操作table示例(个人心得)
Nov 29 Javascript
js实现编辑div节点名称的方法
Dec 17 Javascript
javascript上下方向键控制表格行选中并高亮显示的方法
Feb 13 Javascript
jQuery下拉美化搜索表单效果代码分享
Aug 25 Javascript
laypage分页控件使用实例详解
May 19 Javascript
JS清除字符串中重复值的实现方法
Aug 03 Javascript
js实现表单及时验证功能 用户信息立即验证
Sep 13 Javascript
利用node.js开发cli的完整步骤
Dec 29 Javascript
Vue中插槽slot的使用方法与应用场景详析
Jun 08 Vue.js
用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设计模式 Decorator(装饰模式)
2011/06/26 PHP
PHP常见漏洞攻击分析
2016/02/21 PHP
php实现图片缩略图的方法
2016/03/29 PHP
php面向对象编程self和static的区别
2016/05/08 PHP
PHP PDOStatement::setAttribute讲解
2019/02/01 PHP
JScript内置对象Array中元素的删除方法
2007/03/08 Javascript
模拟用户操作Input元素,不会触发相应事件
2007/05/11 Javascript
jquery select(列表)的操作(取值/赋值)
2009/08/06 Javascript
基于jquery的jqDnR拖拽溢出的修改
2011/02/12 Javascript
JS 获取HTML标签内的子节点的方法
2016/09/21 Javascript
详解vue-cli + webpack 多页面实例应用
2017/04/25 Javascript
vue音乐播放器插件vue-aplayer的配置及其使用实例详解
2017/07/10 Javascript
js精确的加减乘除实例
2017/11/14 Javascript
微信小程序rich-text富文本用法实例分析
2019/05/20 Javascript
JS前端知识点offset,scroll,client,冒泡,事件对象的应用整理总结
2019/06/27 Javascript
js实现轮播图效果 z-index实现轮播图
2020/01/17 Javascript
npm qs模块使用详解
2020/02/07 Javascript
微信小程序自定义yPicker组件实现省市区三级联动功能
2020/10/29 Javascript
Vue 解决在element中使用$notify在提示信息中换行问题
2020/11/11 Javascript
[01:19:33]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第一场 2月2日
2021/03/11 DOTA
python进阶教程之异常处理
2014/08/30 Python
详解python中requirements.txt的一切
2017/03/03 Python
每天迁移MySQL历史数据到历史库Python脚本
2018/04/13 Python
python如何通过twisted搭建socket服务
2020/02/03 Python
台湾最大网路书店:博客来
2018/03/18 全球购物
JAKO-O德国野酷台湾站:德国首屈一指的婴幼童用品品牌
2019/01/14 全球购物
荷兰最大的多品牌男装连锁店:Adam Brandstore
2019/12/31 全球购物
益达广告词
2014/03/14 职场文书
应届生求职自荐信范文
2014/04/07 职场文书
教师个人自我评价范文
2014/04/13 职场文书
2014年师德师风学习材料
2014/05/16 职场文书
禁止酒驾标语
2014/06/25 职场文书
教师节感谢信
2015/01/22 职场文书
2019运动会广播加油稿汇总
2019/08/21 职场文书
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
2022/04/18 MySQL
Java代码规范与质量检测插件SonarLint的使用
2022/08/05 Java/Android