2023年6月21日发(作者:)

[前端]图⽚预加载⽅法  ⽬录1.

2.

3.

4.

1. 使⽤jQuery图⽚预加载(延迟加载)插件Lazy LoadLazy Load也叫惰性加载,延迟加载,顾名思义,就是在图⽚未到达可视区域时,不加载图⽚,我们常常在很多的优秀⽹站上看到类似的例⼦,例如迅雷、⼟⾖、优酷等,由于⼀个⽹页的图⽚⾮常多,⼀次性加载增加服务器压⼒,⽽且⽤户未必会拉到底部,浪费⽤户流量,Lazy Load采⽤按需加载,更快的加载速度从⽽达到优化⽹页的⽬的。使⽤⽅法:加载jQuery, 并在html代码的底部包含进来设置图⽚的占位符为data-original, 给图⽚⼀个特别的标签, 像这样设置图⽚$(function(){

$("").lazyload();

});注意:你必须给图⽚设置⼀个height和width,或者在中定义,否则可能会影响到图⽚的显⽰。插件选项图⽚预先加载距离:threshold,通过设置这个值,在图⽚未出现在可视区域的顶部距离这个值时加载。默认为0,下⾯为设置threshold为200表⽰在图⽚距离可视区域还有200像素时加载。$("").lazyload({ threshold :200});事件绑定加载的⽅式:event,你可以使⽤jQuery的事件,例如“click”、“mouseover”,或者你也可以⾃定义事件,默认等待⽤户滚动,图⽚出现在可视区域。下⾯是使⽤click:$("").lazyload({event:"click"});显⽰效果:effect,默认使⽤show(),你可以使⽤fadeIn(逐渐出现)⽅式,代码如下:$("").lazyload({ effect :"fadeIn"});对于禁⽤javascript的浏览器则要加上noscript内容:图⽚限定在某个容器内:container,你可以通过限定某个容器内容的图⽚才会⽣效,代码如下:#container { height:600px; overflow: scroll;}$("").lazyload({ container: $("#container")});    原⽂链接:

2. JS实现图⽚预加载  在浏览器渲染图⽚的时候, 它获得图⽚的⼀⽚区域的时候, 就已经为这张图⽚预留了⼀⽚空⽩的区域来填充图⽚, 这就是预加载获得图⽚尺⼨最原始的使⽤⽅法.  有时候会加载⼀些在当前页⾯没有⽤到的图⽚,是为了提前加载到缓存⾥,这样后⾯的页⾯就可以直接从缓存读取了。  加载⼤图的时候,我们可以先显⽰模糊的缩略图,等到⼤图加载完了,再把缩略图替换掉,这样填补了图⽚加载期间的空⽩时间。  image也有onload和onerror事件,分别是加载完后和加载失败时执⾏。  Image对象是专门⽤于处理图⽚加载的,就相当于内存中的img标签。  图⽚预加载案例:⿏标移⼊⼀张图⽚时,换成另⼀张图⽚,移出时换回原来的图⽚。正常做法是,⿏标移⼊的时候,改变图⽚的src,但这时就要去加载图⽚了,会等待⼀段时间,这样体验不好。预加载的做法是,在页⾯加载完,⿏标移⼊之前就通过Image对象把图⽚加载进缓存了,这样⿏标移⼊的时候直接从缓存⾥读取了,速度很快。图⽚预加载: if(){ var img = new Image(); = "img/"; }

封装成⼀个预加载图⽚的函数 //实现图⽚的预加载 function preloadImg(srcArr){ if(srcArr instanceof Array){ for(var i=0; i<; i++){ var oImg = new Image(); = srcArr[i]; } } } //预加载图⽚ preloadImg(['image/']); //参数是⼀个url数组  使⽤⼀个回调函数来获得图⽚的属性 function getPreloadImgAttr(url,callback){ var oImg = new Image(); //创建⼀个Image对象,实现图⽚的预加载 = url;   // 看下⼀节,其实应当先进⾏onload的绑定,再赋值给src if(te){ //如果图⽚已经存在于浏览器缓存,直接调⽤回调函数 (oImg); return; //直接返回,不再处理onload事件 } = function(){ //图⽚下载完毕时异步调⽤callback函数 (oImg);

}; } getPreloadImgAttr('image/',function(){ (, ); });  关于预加载图⽚的改进⽹上看到⼀篇博客, 其中指出以上通⽤的⽅法存在⼀些问题:创建了⼀个临时匿名函数来作为图⽚的onload事件处理函数,形成了闭包。相信⼤家都看到过ie下的内存泄漏模式的⽂章,其中有⼀个模式就是循环引⽤,⽽闭包就有保存外部运⾏环境的能⼒(依赖于作⽤域链的实现),所以这个函数内部⼜保存了对img的引⽤,这样就形成了循环引⽤,导致内存泄漏。(这种模式的内存泄漏只存在低版本的ie6中,打过补丁的ie6以及⾼版本的ie都解决了循环引⽤导致的内存泄漏问题)。只考虑了静态图⽚的加载,忽略了gif等动态图⽚,这些动态图⽚可能会多次触发onload。  改进⽅法:function loadImage(url, callback) {

var img = new Image(); //创建⼀个Image对象,实现图⽚的预下载

= function(){ = null; callback(img); } = url;

}  这样内存泄漏,动态图⽚的加载问题都得到了解决,⽽且也以统⼀的⽅式,实现了callback的调⽤。关于这个⽅法, 有个疑问是缓存的问题, 在原⽂⾥也给出了⼀些解释经过对多个浏览器版本的测试,发现ie、opera下,当图⽚加载过⼀次以后,如果再有对该图⽚的请求时,由于浏览器已经缓存住这张图⽚了,不会再发起⼀次新的请求,⽽是直接从缓存中加载过来。对于 firefox和safari,它们试图使这两种加载⽅式对⽤户透明,同样会引起图⽚的onload事件,⽽ie和opera则忽略了这种同⼀性,不会引起图⽚的onload事件,因此上边的代码在它们⾥边不能得以实现效果。      但整体来讲,仍然应该先进⾏onload事件的绑定, 再赋值src  参考:

3. ⽤CSS实现图⽚的预加载  这个概念就是写⼀个CSS样式设置⼀批背景图⽚,然后将其隐藏,这样你就看不到那些图⽚了。那些背景图⽚就是你想预载的图⽚。#preload-01 { background: url(/) no-repeat -9999px -9999px; }

#preload-02 { background: url(/) no-repeat -9999px -9999px; }

#preload-03 { background: url(/) no-repeat -9999px -9999px; }  这⾥为了隐藏这些图⽚, 使⽤了位置设置为极⼤的负值的⽅法. 还可以直接设置 { width: 0; height: 0; display: none};  该⽅法虽然⾼效,但仍有改进余地。使⽤该法加载的图⽚会同页⾯的其他内容⼀起加载,增加了页⾯的整体加载时间。为了解决这个问题,我们增加了⼀些JavaScript代码,来推迟预加载的时间,直到页⾯加载完毕。代码如下:// better image preloading @ /press/2009/12/28/3-ways-preload-images-css-javascript-ajax/

function preloader() {

if (mentById) {

mentById("preload-01").ound = "url(/) no-repeat -9999px -9999px";

mentById("preload-02").ound = "url(/) no-repeat -9999px -9999px";

mentById("preload-03").ound = "url(/) no-repeat -9999px -9999px";

}

}

function addLoadEvent(func) {

var oldonload = ;

if (typeof != 'function') {

= func;

} else {

= function() {

if (oldonload) {

oldonload();

}

func();

}

}

}

addLoadEvent(preloader);  在该脚本的第⼀部分,我们获取使⽤类选择器的元素,并为其设置了background属性,以预加载不同的图⽚。  该脚本的第⼆部分,我们使⽤addLoadEvent()函数来延迟preloader()函数的加载时间,直到页⾯加载完毕。  如果JavaScript⽆法在⽤户的浏览器中正常运⾏,会发⽣什么?很简单,图⽚不会被预加载,当页⾯调⽤图⽚时,正常显⽰即可。  参考:

4. 使⽤Ajax实现预加载  该⽅法利⽤DOM,不仅仅预加载图⽚,还会预加载CSS、JavaScript等相关的东西。使⽤Ajax,⽐直接使⽤JavaScript,优越之处在于JavaScript和CSS的加载不会影响到当前页⾯。该⽅法简洁、⾼效。 = function() {

setTimeout(function() {

// XHR to request a JS and a CSS

var xhr = new XMLHttpRequest();

('GET', '/');

('');

xhr = new XMLHttpRequest();

('GET', '/');

('');

// preload image

new Image().src = "/";

}, 1000);

};    上⾯代码预加载了“”、“”和“”。1000毫秒的超时是为了防⽌脚本挂起,⽽导致正常页⾯出现功能问题。  与之相⽐, 如果⽤js的话, 要实现以上加载过程则会应⽤到页⾯上. 实现如下 = function() {

setTimeout(function() {

// reference to

var head = mentsByTagName('head')[0];

// a new CSS

var css = Element('link');

= "text/css";

= "stylesheet";

= "/";

// a new JS

var js = Element("script");

= "text/javascript";

= "/";

// preload JS and CSS

Child(css);

Child(js);

// preload image

new Image().src = "/";

}, 1000);

};

  这⾥,我们通过DOM创建三个元素来实现三个⽂件的预加载。正如上⾯提到的那样,使⽤Ajax,加载⽂件不会应⽤到加载页⾯上。从这点上看,Ajax⽅法优越于JavaScript。  参考:

2023年6月21日发(作者:)

[前端]图⽚预加载⽅法  ⽬录1.

2.

3.

4.

1. 使⽤jQuery图⽚预加载(延迟加载)插件Lazy LoadLazy Load也叫惰性加载,延迟加载,顾名思义,就是在图⽚未到达可视区域时,不加载图⽚,我们常常在很多的优秀⽹站上看到类似的例⼦,例如迅雷、⼟⾖、优酷等,由于⼀个⽹页的图⽚⾮常多,⼀次性加载增加服务器压⼒,⽽且⽤户未必会拉到底部,浪费⽤户流量,Lazy Load采⽤按需加载,更快的加载速度从⽽达到优化⽹页的⽬的。使⽤⽅法:加载jQuery, 并在html代码的底部包含进来设置图⽚的占位符为data-original, 给图⽚⼀个特别的标签, 像这样设置图⽚$(function(){

$("").lazyload();

});注意:你必须给图⽚设置⼀个height和width,或者在中定义,否则可能会影响到图⽚的显⽰。插件选项图⽚预先加载距离:threshold,通过设置这个值,在图⽚未出现在可视区域的顶部距离这个值时加载。默认为0,下⾯为设置threshold为200表⽰在图⽚距离可视区域还有200像素时加载。$("").lazyload({ threshold :200});事件绑定加载的⽅式:event,你可以使⽤jQuery的事件,例如“click”、“mouseover”,或者你也可以⾃定义事件,默认等待⽤户滚动,图⽚出现在可视区域。下⾯是使⽤click:$("").lazyload({event:"click"});显⽰效果:effect,默认使⽤show(),你可以使⽤fadeIn(逐渐出现)⽅式,代码如下:$("").lazyload({ effect :"fadeIn"});对于禁⽤javascript的浏览器则要加上noscript内容:图⽚限定在某个容器内:container,你可以通过限定某个容器内容的图⽚才会⽣效,代码如下:#container { height:600px; overflow: scroll;}$("").lazyload({ container: $("#container")});    原⽂链接:

2. JS实现图⽚预加载  在浏览器渲染图⽚的时候, 它获得图⽚的⼀⽚区域的时候, 就已经为这张图⽚预留了⼀⽚空⽩的区域来填充图⽚, 这就是预加载获得图⽚尺⼨最原始的使⽤⽅法.  有时候会加载⼀些在当前页⾯没有⽤到的图⽚,是为了提前加载到缓存⾥,这样后⾯的页⾯就可以直接从缓存读取了。  加载⼤图的时候,我们可以先显⽰模糊的缩略图,等到⼤图加载完了,再把缩略图替换掉,这样填补了图⽚加载期间的空⽩时间。  image也有onload和onerror事件,分别是加载完后和加载失败时执⾏。  Image对象是专门⽤于处理图⽚加载的,就相当于内存中的img标签。  图⽚预加载案例:⿏标移⼊⼀张图⽚时,换成另⼀张图⽚,移出时换回原来的图⽚。正常做法是,⿏标移⼊的时候,改变图⽚的src,但这时就要去加载图⽚了,会等待⼀段时间,这样体验不好。预加载的做法是,在页⾯加载完,⿏标移⼊之前就通过Image对象把图⽚加载进缓存了,这样⿏标移⼊的时候直接从缓存⾥读取了,速度很快。图⽚预加载: if(){ var img = new Image(); = "img/"; }

封装成⼀个预加载图⽚的函数 //实现图⽚的预加载 function preloadImg(srcArr){ if(srcArr instanceof Array){ for(var i=0; i<; i++){ var oImg = new Image(); = srcArr[i]; } } } //预加载图⽚ preloadImg(['image/']); //参数是⼀个url数组  使⽤⼀个回调函数来获得图⽚的属性 function getPreloadImgAttr(url,callback){ var oImg = new Image(); //创建⼀个Image对象,实现图⽚的预加载 = url;   // 看下⼀节,其实应当先进⾏onload的绑定,再赋值给src if(te){ //如果图⽚已经存在于浏览器缓存,直接调⽤回调函数 (oImg); return; //直接返回,不再处理onload事件 } = function(){ //图⽚下载完毕时异步调⽤callback函数 (oImg);

}; } getPreloadImgAttr('image/',function(){ (, ); });  关于预加载图⽚的改进⽹上看到⼀篇博客, 其中指出以上通⽤的⽅法存在⼀些问题:创建了⼀个临时匿名函数来作为图⽚的onload事件处理函数,形成了闭包。相信⼤家都看到过ie下的内存泄漏模式的⽂章,其中有⼀个模式就是循环引⽤,⽽闭包就有保存外部运⾏环境的能⼒(依赖于作⽤域链的实现),所以这个函数内部⼜保存了对img的引⽤,这样就形成了循环引⽤,导致内存泄漏。(这种模式的内存泄漏只存在低版本的ie6中,打过补丁的ie6以及⾼版本的ie都解决了循环引⽤导致的内存泄漏问题)。只考虑了静态图⽚的加载,忽略了gif等动态图⽚,这些动态图⽚可能会多次触发onload。  改进⽅法:function loadImage(url, callback) {

var img = new Image(); //创建⼀个Image对象,实现图⽚的预下载

= function(){ = null; callback(img); } = url;

}  这样内存泄漏,动态图⽚的加载问题都得到了解决,⽽且也以统⼀的⽅式,实现了callback的调⽤。关于这个⽅法, 有个疑问是缓存的问题, 在原⽂⾥也给出了⼀些解释经过对多个浏览器版本的测试,发现ie、opera下,当图⽚加载过⼀次以后,如果再有对该图⽚的请求时,由于浏览器已经缓存住这张图⽚了,不会再发起⼀次新的请求,⽽是直接从缓存中加载过来。对于 firefox和safari,它们试图使这两种加载⽅式对⽤户透明,同样会引起图⽚的onload事件,⽽ie和opera则忽略了这种同⼀性,不会引起图⽚的onload事件,因此上边的代码在它们⾥边不能得以实现效果。      但整体来讲,仍然应该先进⾏onload事件的绑定, 再赋值src  参考:

3. ⽤CSS实现图⽚的预加载  这个概念就是写⼀个CSS样式设置⼀批背景图⽚,然后将其隐藏,这样你就看不到那些图⽚了。那些背景图⽚就是你想预载的图⽚。#preload-01 { background: url(/) no-repeat -9999px -9999px; }

#preload-02 { background: url(/) no-repeat -9999px -9999px; }

#preload-03 { background: url(/) no-repeat -9999px -9999px; }  这⾥为了隐藏这些图⽚, 使⽤了位置设置为极⼤的负值的⽅法. 还可以直接设置 { width: 0; height: 0; display: none};  该⽅法虽然⾼效,但仍有改进余地。使⽤该法加载的图⽚会同页⾯的其他内容⼀起加载,增加了页⾯的整体加载时间。为了解决这个问题,我们增加了⼀些JavaScript代码,来推迟预加载的时间,直到页⾯加载完毕。代码如下:// better image preloading @ /press/2009/12/28/3-ways-preload-images-css-javascript-ajax/

function preloader() {

if (mentById) {

mentById("preload-01").ound = "url(/) no-repeat -9999px -9999px";

mentById("preload-02").ound = "url(/) no-repeat -9999px -9999px";

mentById("preload-03").ound = "url(/) no-repeat -9999px -9999px";

}

}

function addLoadEvent(func) {

var oldonload = ;

if (typeof != 'function') {

= func;

} else {

= function() {

if (oldonload) {

oldonload();

}

func();

}

}

}

addLoadEvent(preloader);  在该脚本的第⼀部分,我们获取使⽤类选择器的元素,并为其设置了background属性,以预加载不同的图⽚。  该脚本的第⼆部分,我们使⽤addLoadEvent()函数来延迟preloader()函数的加载时间,直到页⾯加载完毕。  如果JavaScript⽆法在⽤户的浏览器中正常运⾏,会发⽣什么?很简单,图⽚不会被预加载,当页⾯调⽤图⽚时,正常显⽰即可。  参考:

4. 使⽤Ajax实现预加载  该⽅法利⽤DOM,不仅仅预加载图⽚,还会预加载CSS、JavaScript等相关的东西。使⽤Ajax,⽐直接使⽤JavaScript,优越之处在于JavaScript和CSS的加载不会影响到当前页⾯。该⽅法简洁、⾼效。 = function() {

setTimeout(function() {

// XHR to request a JS and a CSS

var xhr = new XMLHttpRequest();

('GET', '/');

('');

xhr = new XMLHttpRequest();

('GET', '/');

('');

// preload image

new Image().src = "/";

}, 1000);

};    上⾯代码预加载了“”、“”和“”。1000毫秒的超时是为了防⽌脚本挂起,⽽导致正常页⾯出现功能问题。  与之相⽐, 如果⽤js的话, 要实现以上加载过程则会应⽤到页⾯上. 实现如下 = function() {

setTimeout(function() {

// reference to

var head = mentsByTagName('head')[0];

// a new CSS

var css = Element('link');

= "text/css";

= "stylesheet";

= "/";

// a new JS

var js = Element("script");

= "text/javascript";

= "/";

// preload JS and CSS

Child(css);

Child(js);

// preload image

new Image().src = "/";

}, 1000);

};

  这⾥,我们通过DOM创建三个元素来实现三个⽂件的预加载。正如上⾯提到的那样,使⽤Ajax,加载⽂件不会应⽤到加载页⾯上。从这点上看,Ajax⽅法优越于JavaScript。  参考: