Track Image Loading效果代码分析
Track Image Loading效果代码分析
发布时间:2016-12-30 来源:查字典编辑
摘要:目的在图片的加载过程中,提供定义图片加载成功或加载失败/超时时的回调函数,并确保执行。动机原生JavaScript已经对Image对象提供了...

目的

在图片的加载过程中,提供定义图片加载成功或加载失败/超时时的回调函数,并确保执行。

动机

原生JavaScript已经对Image对象提供了onload和onerror注册事件。但在浏览器缓存及其他因素的影响下,用户在使用回退按钮或者刷新页面时onload事件常常未能稳定触发。在我开发的相册系统中,我希望图片能根据自定义的大小显示以免导致页面变形,例如最宽不得超过500px,而小于500px宽度的图片则按原大小显示。CSS2提供了max-width属性能够帮组我们实现这一目的。但很遗憾,挨千刀的IE6并不支持。

IE6一个弥补的办法就是通过注册img.onload事件,待图片加载完成后自动调整大小。以下代码取自著名的Discuz!论坛系统4.1版本对显示图片的处理。

<imgsrc="http://img8.imagepile.net/img8/47104p155.jpg"border="0"

onload="if(this.width>screen.width*0.7){this.resized=true;this.width=screen.width*0.7;

this.alt='ClickheretoopennewwindownCTRL+Mousewheeltozoomin/out';}"

onmouseover="if(this.width>screen.width*0.7){this.resized=true;this.width=screen.width*0.7;this.style.cursor='hand';this.alt='ClickheretoopennewwindownCTRL+Mousewheeltozoomin/out';}"

onclick="if(!this.resized){returntrue;}else{window.open('http://img8.imagepile.net/img8/47104p155.jpg');}"

onmousewheel="returnimgzoom(this);">

前文已述,浏览器并不保证事件处理函数执行。所以需要一个更稳定的方式跟踪图片加载过程,并执行设定的回调函数。

实现

image.complete属性标示的是图片加载状态,其值如果为ture,则表示加载成功。图片不存在或加载超时则值为false。利用setInterval()函数定时检查该状态则可以实现跟踪图片加载的状况。代码片断如下:

ImageLoader=Class.create();

ImageLoader.prototype={

initialize:function(options){

this.options=Object.extend({

timeout:60,//60s

onInit:Prototype.emptyFunction,

onLoad:Prototype.emptyFunction,

onError:Prototype.emptyFunction

},options||{});

this.images=[];

this.pe=newPeriodicalExecuter(this._load.bind(this),0.02);

},

........

}

利用Prototype的PeriodicalExecuter类创建一个定时器,每隔20毫秒检查一次图片的加载情况,并根据状态执行options参数中定义的回调函数。

使用

varloader=newImageLoader({

timeout:30,

onInit:function(img){

img.style.width='100px';

},

onLoad:function(img){

img.style.width='';

if(img.width>500)

img.style.width='500px';

},

onError:function(img){

img.src='error.jpg';//hintimage

}

});loader.loadImage(document.getElementsByTagName('img'));

上面的代码定义图片最初以100px显示,加载成功后如果图片实际宽度超过500px,则再强制定义为500px,否则显示原大小。如果图片不存在或加载超时(30秒为超时),则显示错误图片。

同理,可以应用ImageLoader的回调函数来根据需求自定义效果,例如默认显示loading,加载完成后再显示原图;图片首先灰度显示,加载完成后再恢复亮度等等。例如:

//needscriptaculouseffects.js

varloader=newImageLoader({

onInit:function(img){

Element.setOpacity(img,0.5);//默认5级透明

},

onLoad:function(img){

Effect.Appear(img);//恢复原图显示

}

});

附示例中包含完整的代码及使用pconline图片为例的测试,注意范例中使用了最新的Prototype1.5.0_rc1。

<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0//EN">

<html>

<head>

<scriptsrc="prototype1.5.0_rc1.js"></script>

<scriptsrc="validation1.5.3/effects.js"></script>

</head>

<body>

<imgid="img0"src="http://img.pconline.com.cn/images/photoblog/2026024/20069/14/1158169144171.jpg"/>

<imgid="img1"src="http://img.pconline.com.cn/images/photoblog/2026024/20069/14/1158169158366.jpg"/>

<imgid="img2"src="http://img.pconline.com.cn/images/photoblog/2026024/20069/14/1158169169983_mthumb.jpg"/>

<br/>加载失败测试<br/>

<imgid="img2"src="http://img.pconline.com.cn/images/photoblog/2026024/20069/14/000000000000.jpg"/>

<scripttype="text/javascript">

ImageLoader=Class.create();

ImageLoader.prototype={

initialize:function(options){

this.options=Object.extend({

timeout:60,//60s

onInit:Prototype.emptyFunction,

onLoad:Prototype.emptyFunction,

onError:Prototype.emptyFunction

},options||{});

this.images=[];

this.pe=newPeriodicalExecuter(this._load.bind(this),0.02);

},

loadImage:function(){

varself=this;

$A(arguments).each(function(img){

if(typeof(img)=='object')

$A(img).each(self._addImage.bind(self));

else

self._addImage(img);

});

},

_addImage:function(img){

img=$(img);

img.onerror=this._onerror.bind(this,img);

this.options.onInit.call(this,img);

if(this.options.timeout>0){

setTimeout(this._ontimeout.bind(this,img),this.options.timeout*1000);

}

this.images.push(img);

if(!this.pe.timer)

this.pe.registerCallback();

},

_load:function(){

this.images=this.images.select(this._onload.bind(this));

if(this.images.length==0){

this.pe.stop();

}

},

_checkComplete:function(img){

if(img._error){

returntrue;

}else{

returnimg.complete;

}

},

_onload:function(img){

if(this._checkComplete(img)){

this.options.onLoad.call(this,img);

img.onerror=null;

if(img._error)

try{deleteimg._error}catch(e){}

returnfalse;

}

returntrue;

},

_onerror:function(img){

img._error=true;

img.onerror=null;

this.options.onError.call(this,img);

},

_ontimeout:function(img){

if(!this._checkComplete(img)){

this._onerror(img);

}

}

}

varloader=newImageLoader({

timeout:30,

onInit:function(img){

img.style.width='100px';

},

onLoad:function(img){

img.style.width='';

if(img.width>500){

img.style.width='500px';

}

},

onError:function(img){

img.src='http://img.pconline.com.cn/nopic.gif';

}

});

loader.loadImage(document.getElementsByTagName('img'));

/*

varloader=newImageLoader({

timeout:30,

onInit:function(img){

Element.setOpacity(img,0.5);

},

onLoad:function(img){

Effect.Appear(img);

},

onError:function(img){

img.src='http://img.pconline.com.cn/nopic.gif';

}

});

*/

/*

$A(document.getElementsByTagName('img')).each(

function(img){

img.onload=function(){

img.style.width='300px';

}

}

);

*/

</script>

</body>

</html>

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Javascript教程学习
热门Javascript教程学习
编程开发子分类