图片延迟加载也称懒加载,通常应用于图片比较多的网页,如果一个页面图片比较多,且页面高度或宽度有好几屏,页面初次加载时,只显示可视区 域的图片,当页面滚动的时候,图片进入了可视区域再进行加载,这样可以显著的提高页面的加载速度,更少的图片并发请求数也可以减轻服务器的压力。如果用户 仅仅在首屏停留,还可以节省流量。如果TAB中的图片较多,也同样可以应用于TAB中,当触发TAB时再进行图片的加载。
图片延迟加载的原理比较简单,先将图片的真实地址缓存在一个自定义的属性(lazy-src)中,而src地址使用一个1×1的全透明的占位图片来代替,当然占位图片也可以是其他的图片。
1 |
<img src= "images/placeholder.png" lazy-src= "images/realimg.jpg" />
|
因为是使用javascript来加载图片,如果用户禁用了javascript,可以设置一个替代的方案。
1 |
<img src= "images/placeholder.png" lazy-src= "images/realimg.jpg" alt= "" />
|
2 |
<noscript><img src= "images/realimg.jpg" alt= "" /></noscript>
|
页面初次加载时获取图片在页面中的位置并缓存(每次取offset的值会引发页面的reflow),计算出可视区域,当图片的位置出现在可视区域中,将src的值替换成真实的地址,此时图片就开始加载了。
当页面滚动的时候,再判断图片已经缓存的位置值是否出现在可视区域内,进行替换src加载。当所有的图片都加载完之后,将相应的触发事件卸载,避免 重复操作引起的内存泄漏。将整个窗口看成是一个大容器,那么也可以在页面中设置一个小容器,在小容器中也同样可以实现图片的延迟加载。
下面是实现的代码,我写成了jQuery插件。
001 |
(function( $ ){ |
002 |
$.fn.imglazyload = function( options ){ |
003 |
var o = $.extend({
|
004 |
attr : 'lazy-src' ,
|
005 |
container : window,
|
006 |
event : 'scroll' ,
|
007 |
fadeIn : false ,
|
008 |
threshold : 0,
|
009 |
vertical : true |
010 |
}, options ),
|
011 |
012 |
event = o. event ,
|
013 |
vertical = o.vertical,
|
014 |
container = $( o.container ),
|
015 |
threshold = o.threshold,
|
016 |
// 将jQuery对象转换成DOM数组便于操作
|
017 |
elems = $.makeArray( $( this ) ),
|
018 |
dataName = 'imglazyload_offset' ,
|
019 |
OFFSET = vertical ? 'top' : 'left' ,
|
020 |
SCROLL = vertical ? 'scrollTop' : 'scrollLeft' ,
|
021 |
winSize = vertical ? container.height() : container.width(),
|
022 |
scrollCoord = container[ SCROLL ](),
|
023 |
docSize = winSize + scrollCoord;
|
024 |
|
025 |
// 延迟加载的触发器
|
026 |
var trigger = {
|
027 |
028 |
init : function( coord ){
|
029 |
return coord >= scrollCoord &&
|
030 |
coord <= ( docSize + threshold );
|
031 |
},
|
032 |
033 |
scroll : function( coord ){
|
034 |
var scrollCoord = container[ SCROLL ]();
|
035 |
return coord >= scrollCoord &&
|
036 |
coord <= ( winSize + scrollCoord + threshold );
|
037 |
},
|
038 |
|
039 |
resize : function( coord ){
|
040 |
var scrollCoord = container[ SCROLL ](),
|
041 |
winSize = vertical ?
|
042 |
container.height() :
|
043 |
container.width();
|
044 |
return coord >= scrollCoord &&
|
045 |
coord <= ( winSize + scrollCoord + threshold );
|
046 |
}
|
047 |
};
|
048 |
|
049 |
var loader = function( triggerElem, event ){
|
050 |
var i = 0,
|
051 |
isCustom = false ,
|
052 |
isTrigger, coord, elem, $elem, lazySrc;
|
053 |
|
054 |
// 自定义事件只要触发即可,无需再判断
|
055 |
if ( event ){
|
056 |
if ( event !== 'scroll' && event !== 'resize' ){
|
057 |
isCustom = true ;
|
058 |
}
|
059 |
}
|
060 |
else {
|
061 |
event = 'init' ;
|
062 |
}
|
063 |
|
064 |
for ( ; i < elems.length; i++ ){
|
065 |
isTrigger = false ;
|
066 |
elem = elems[i];
|
067 |
$elem = $( elem );
|
068 |
lazySrc = $elem.attr( o.attr );
|
069 |
|
070 |
if ( !lazySrc || elem.src === lazySrc ){
|
071 |
continue ;
|
072 |
}
|
073 |
// 先从缓存获取offset值,缓存中没有才获取计算值,
|
074 |
// 将计算值缓存,避免重复获取引起的reflow
|
075 |
coord = $elem.data( dataName );
|
076 |
|
077 |
if ( coord === undefined ){
|
078 |
coord = $elem.offset()[ OFFSET ];
|
079 |
$elem.data( dataName, coord );
|
080 |
}
|
081 |
082 |
isTrigger = isCustom || trigger[ event ]( coord );
|
083 |
084 |
if ( isTrigger ){
|
085 |
// 加载图片
|
086 |
elem.src = lazySrc;
|
087 |
if ( o.fadeIn ){
|
088 |
$elem.hide().fadeIn();
|
089 |
}
|
090 |
// 移除缓存
|
091 |
$elem.removeData( dataName );
|
092 |
// 从DOM数组中移除该DOM
|
093 |
elems.splice( i--, 1 );
|
094 |
}
|
095 |
}
|
096 |
097 |
// 所有的图片加载完后卸载触发事件
|
098 |
if ( !elems.length ){
|
099 |
if ( triggerElem ){
|
100 |
triggerElem.unbind( event , fire );
|
101 |
}
|
102 |
else {
|
103 |
container.unbind( o. event , fire );
|
104 |
}
|
105 |
$( window ).unbind( 'resize' , fire );
|
106 |
elems = null ;
|
107 |
}
|
108 |
|
109 |
};
|
110 |
|
111 |
var fire = function( e ){
|
112 |
loader( $( this ), e.type );
|
113 |
};
|
114 |
|
115 |
// 绑定事件
|
116 |
container = event === 'scroll' ? container : $( this );
|
117 |
container.bind( event , fire );
|
118 |
$( window ).bind( 'resize' , fire );
|
119 |
120 |
// 初始化
|
121 |
loader();
|
122 |
123 |
return this ;
|
124 |
}; |
125 |
126 |
})( jQuery ); |
调用:
1 |
$( 'img' ).imglazyload({
|
2 |
event : 'scroll' ,
|
3 |
attr : 'lazy-src'
|
4 |
}); |
默认的调用可以省略所有参数。
1 |
$( '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。
图片延迟加载的插件下载地址:http://stylechen.com/wp-content/uploads/download/imglazyload.zip