一、为什么要使用图片预加载
在浏览器渲染图片的时候, 它获得图片的一片区域的时候, 就由上至下逐渐地填充满图片区域原来的留白部分(其中这种原本的留白就是预加载获得图片尺寸最原始的使用方法)。这样每打开一张新的链接图片的时候,就需要等待着这个缓慢的填充过程,体验非常不好。使用图片预加载就是将想要查看的一系列图片先统一全部提前进行加载,这个期间可以是一段等待的动画,待加载完毕之后就可以快速的直接显示出来,取代了原本逐渐填充留白的过程。换句话说呢,就是将原来每打开一张新的图片之前的等待时间全部统一合并到了同一个时间段了,将多次的等待变成一次的等待,并将这个等待过程转变为观感友好的等待动画、文字。
二、图片预加载的主要思路
图片预加载的主要思路就是把稍后需要用到的图片悄悄的提前加载到本地,因为浏览器有缓存的原因,如果稍后用到这个url的图片了,浏览器会优先从本地缓存找该url对应的图片,如果图片没过期的话,就使用这个图片。
三、实现图片预加载的方法
1、JS实现图片预加载
适用js的image对象也有onload和onerror事件,分别是加载完后和加载失败时执行。
Image对象是专门用于处理图片加载的,就相当于内存中的img标签。
.单个图片进行预加载
function getPreloadImgAttr(url,callback){
var oImg = new Image(); //创建一个Image对象,实现图片的预加载
if(oImg.complete){
//如果图片已经存在于浏览器缓存,直接调用回调函数
callback.call(oImg);
return; //直接返回,不再处理onload事件
}
oImg.onload = function(){
//图片下载完毕时异步调用callback函数
callback.call(oImg);
};
oImg.src = url; // 应当先进行onload的绑定,再赋值给src
}
getPreloadImgAttr('image/example.jpg',function(){
console.log(this.width, this.height);
});
其中oImg.src=url之所以要放在那里的具体原因见关于图片预加载你所不知道的。
.封装好的一个或者多个图片预加载的插件(jquery版)
//图片预加载的插件封装,面向对象的写法
//使用闭包来模拟局部作用域
(function($){
function PreLooad(imags,options){
this.imgs=(typeof imgs==="string")? [imgs]:imags;//传进来的可能是单张图片或者数组,写插件就是要将问题尽可能的抽象化,并且考虑兼容多种情况
this.opts=$.extend({},PreLoad.DEFAULTS,options);//传进来的变量和默认值的融合,如果没有传进来就使用默认,实质是将后一个对象覆盖前一个合并为一个对象
this._unordered();
}
PreLooad.DEFAULTS={//设置默认参数
each:null,//每一张图片加载完毕后执行
all:null//所有图片加载完毕后执行
};
//写在原型上这样每次实例化的时候,都保持只有一份,减少生成量
PreLooad.prototype._unordered=function(){
//无序加载
var imgs = this.imgs,
opts= this.opts,
count = 0,
len = imgs.length;
$.each(imgs, function (i, src) {
if (typeof src != 'string') {
return;
}
var imgObj = new Image();
$(imgObj).on('load error', function () {
opts.each && opts.each(count);//判断 opts存不存在,若不存在执行后续的会报错
if (count >= len - 1) {
opts.all && opts.all();
}
count++;
});
imgObj.src = src;
});
};
//封装为插件
//方法一,需要绑定到一个元素上
// $.fn.extend->$("#img").preLoad;
//方法二,单独的工具方法
// $.extend->$.preLoad();
$.extend({
preload:function(imgs,opts){
new PreLoad(imgs,opts);//实例化
}
})
})(jQuery)
$.preload(imgs,{//插件调用
each:function (count) {
$progress.html(Math.round((count+1)/len *100)+'%');
},
all:function () {
$('.loading').hide();
document.title = '1/'+len;
}
});
2、css实现图片预加载
这个概念就是写一个CSS样式设置一批背景图片,然后将其隐藏,这样你就看不到那些图片了。那些背景图片就是你想预载的图片。
#preload-01 { background: url(http://domain.tld/image-01.png) no-repeat -9999px -9999px; }
#preload-02 { background: url(http://domain.tld/image-02.png) no-repeat -9999px -9999px; }
#preload-03 { background: url(http://domain.tld/image-03.png) no-repeat -9999px -9999px; }
这里为了隐藏这些图片, 使用了位置设置为极大的负值的方法. 还可以直接设置 { width: 0; height: 0; display: none};
将这三个ID选择器应用到(X)html元素中,我们便可通过CSS的background属性将图片预加载到屏幕外的背景上。只要这些图片的路径保持不变,当它们在web页面的其他地方被调用时,浏览器就会在渲染过程中使用预加载(缓存)的图片。简单、高效,不需要任何JavaScript。
该方法虽然高效,但仍有改进余地。使用该法加载的图片会同页面的其他内容一起加载,增加了页面的整体加载时间。为了解决这个问题,我们增加了一些JavaScript代码,来推迟预加载的时间,直到页面加载完毕。代码如下:
function preloader() {
if (document.getElementById) {
document.getElementById("preload-01").style.background = "url(http://domain.tld/image-01.png) no-repeat -9999px -9999px";
document.getElementById("preload-02").style.background = "url(http://domain.tld/image-02.png) no-repeat -9999px -9999px";
document.getElementById("preload-03").style.background = "url(http://domain.tld/image-03.png) no-repeat -9999px -9999px";
}
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(preloader);
在该脚本的第一部分,我们获取使用类选择器的元素,并为其设置了background属性,以预加载不同的图片。
该脚本的第二部分,我们使用addLoadEvent()函数来延迟preloader()函数的加载时间,直到页面加载完毕。
如果JavaScript无法在用户的浏览器中正常运行,会发生什么?很简单,图片不会被预加载,当页面调用图片时,正常显示即可。
3、使用Ajax实现预加载
该方法利用DOM,不仅仅预加载图片,还会预加载CSS、JavaScript等相关的东西。使用Ajax,比直接使用JavaScript,优越之处在于JavaScript和CSS的加载不会影响到当前页面。该方法简洁、高效。
window.onload = function() {
setTimeout(function() {
// XHR to request a JS and a CSS
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain.tld/preload.js');
xhr.send('');
xhr = new XMLHttpRequest();
xhr.open('GET', 'http://domain.tld/preload.css');
xhr.send('');
// preload image
new Image().src = "http://domain.tld/preload.png";
}, 1000);
};
上面代码预加载了“preload.js”、“preload.css”和“preload.png”。1000毫秒的超时是为了防止脚本挂起,而导致正常页面出现功能问题。
4、使用jQuery图片预加载(延迟加载)插件Lazy Load