图片预加载是web开发中一种应用相当广泛的技术,比如我们在做图片翻转显示等特效的时候,为了让图片在转换的时候不出现等待,我们最好是先让图片下载到本地,然后在继续执行后续的操作。今天我们将来实现一个完整的图片预加载和处理图片加载后执行后续操作的代码。
下面的函数实现了一个我们想要的最基本的图片预加载效果
1 function preloadimages(arr){ 2 var newimages=[] 3 var arr=(typeof arr!="object")? [arr] : arr //确保参数总是数组 4 for (var i=0; i<arr.length; i++){ 5 newimages[i]=new Image() 6 newimages[i].src=arr[i] 7 } 8 }
我们可以通过如下的方式加载我们想要的图片
1 preloadimages(['1.gif', '2.gif', '3.gif'])
上面的方法已经可以满足我们最基本的预加载图片的效果了,但情况往往并不如此,我们往往需要确切的知道图像是否被真正加载完成,并可能在后续执行一系列对图片的操作功能。幸运的是,这个功能实现起来并不难,我们可以使用onload和onerror事件去处理决定图片是否加载完成(或者失败)。在本文的最终实现代码中,我们将会把proloadimages()函数改造成如下的样子。
1 preloadimages(['1.gif', '2.gif', '3.gif']).done(function(images){ 2 //当图片全部加载完成之后,执行此处的代码 3 //images参数是Array类型,对应加载进来的图像 4 //images[0] 对应的是第一张图像 5 })
首先我们用image对象的onload和onerror事件处理函数来检测图片的加载情况(成功或失败),改造后的代码如下。
1 function preloadimages(arr){ 2 var newimages=[], loadedimages=0 3 var arr=(typeof arr!="object")? [arr] : arr 4 function imageloadpost(){ 5 loadedimages++ 6 if (loadedimages==arr.length){ 7 alert("图片已经加载完成") 8 } 9 } 10 for (var i=0; i<arr.length; i++){ 11 newimages[i]=new Image() 12 newimages[i].src=arr[i] 13 newimages[i].onload=function(){ 14 imageloadpost() 15 } 16 newimages[i].onerror=function(){ 17 imageloadpost() 18 } 19 } 20 }
我们可以使用代码2的调用方法测试该函数,当图片全部加载完成(成功或失败)后,浏览器将会弹出“图片已经加载完成”的消息。
现在,我们将为preloadimages()函数增加一个回调函数来处理后续的操作
通常我们会为我们的preloadimages()函数增加一个匿名函数做为参数,来完成我们需要的功能。如此之后,我们调用preloadimages()函数的代码可能会如下面这样。
1 preloadimages(imagesarray, function(){ 2 //图片加载完成之后执行的操作 3 })
但是我们现在来做一点点改变,让代码看起来更直观,更易于理解,改造完成之后,preloadimages()函数的调用看起来如下所示。
1 preloadimages(imagesarray).done(function(){ 2 //图片加载完成后的操作 3 })
上面这种写法大家一看一定都会觉得非常清晰明了,那么接下来,我们继续来改造我们的preloadimages()函数。
1 function preloadimages(arr){ 2 var newimages=[], loadedimages=0 3 var postaction=function(){} //此处增加了一个postaction函数 4 var arr=(typeof arr!="object")? [arr] : arr 5 function imageloadpost(){ 6 loadedimages++ 7 if (loadedimages==arr.length){ 8 postaction(newimages) //加载完成用我们调用postaction函数并将newimages数组做为参数传递进去 9 } 10 } 11 for (var i=0; i<arr.length; i++){ 12 newimages[i]=new Image() 13 newimages[i].src=arr[i] 14 newimages[i].onload=function(){ 15 imageloadpost() 16 } 17 newimages[i].onerror=function(){ 18 imageloadpost() 19 } 20 } 21 return { //此处返回一个空白对象的done方法 22 done:function(f){ 23 postaction=f || postaction 24 } 25 } 26 }
上面的代码,我们稍作修改了几个地方:
首先,我们增加了一个postaction函数,该函数被用来做为图片加载完成后的回调函数,用户可以在后面调用的时候用自己的处理函数覆盖掉该函数。
第二,我们的preloadimages()函数返回了一个空对象,其中包含一个简单的done()方法,这是实现本次改造的关键所在,确保了链式调用的实现。
最后,我们的调用变为如下形式
1 preloadimages(['1.gif', '2.gif', '3.gif']).done(function(images){ 2 alert(images.length) //alerts 3 3 alert(images[0].src+" "+images[0].width) //alerts '1.gif 220' 4 })
当然,我们还可以在done()里实现各种我们需要的图片操作!