图片预加载
2013-07-16 19:13 臭小子1983 阅读(611) 评论(0) 编辑 收藏 举报资源预加载可以提升用户体验,如果每次用户打开页面都要加载图片,js,css等资源,会影响用户体验。资源预加载可以一定程度上改善这种情况。
我们可以做的是,但第一个页面load完的时候,在用户阅读网页的空隙,把下一个页面所用的资源提前加载过来cache住,这样下个页面就直接读缓存资源了,这样可以一定程度改善用户体验。
那么预加载资源需要解决的主要问题是JS加载过来不会被直接执行,css加载过来不会更改页面样式。
一、Image对象的属性和方法
1、src:图片的路径
2、title:图征的
3、onload:图片载入完成后调用的事件
4、complete、readyState:图片载入成功调用的事件IE专有
code:
<input type="button" name="" value="载入图片" onclick="addImg('http://ossweb-img.qq.com/upload/adw/image/201307/1373323962034898366.jpg')"> <script type="text/javascript"> function addImg(isrc){ var Img = new Image(); Img.src = isrc; Img.onload = function (){ document.body.appendChild(Img); } } </script>
页面打开时并没有加载图片,当点击按钮时将图片载入进来,在ie和opera中点完一次在点就不会在出来图片是因为缓存机制
修改一下code:
<input type="button" name="" value="载入图片" onclick="addImg('http://ossweb-img.qq.com/upload/adw/image/201307/1373323962034898366.jpg')"> <script type="text/javascript"> function addImg(isrc){ var Img = new Image(); Img.onload = function (){ document.body.appendChild(Img); } Img.src = isrc; } </script>
这样就将问题解决了
二、图片预加载技术的典型应用:
如lightbox方式展现照片,无疑需要提前获得大图的尺寸,这样才能居中定位,由于javascript无法获取img文件头数据,必须等待其加载完毕后才能获取真实的大小然后展示出来,所以lightbox显示的图片的速度体验要比直接输出的差很多,而本文说提到的预加载技术主要针对获取图片尺寸。
一段典型的使用预加载获取图片大小的例子:
1 var imgLoad = function (url, callback) { 2 var img = new Image(); 3 img.src = url; 4 if (img.complete) { 5 callback(img.width, img.height); 6 } else { 7 img.onload = function () { 8 callback(img.width, img.height); 9 img.onload = null; 10 }; 11 }; 12 };
web应用程序区别于桌面应用程序,响应速度才是最好的用户体验。如果想要速度与优雅兼得,那就必须提前获得图片尺寸,如何在图片没有加载完毕就能获取图片尺寸?
三、结合flash加载图片,获取图片头部数据的尺寸
flash虽然很强大,但它与生俱来的缺点让人爱恨交织,加上很多移动设备不支持falsh无疑更是致命的伤,还是放弃吧。
四、在服务端保存图片尺寸数据
这里不得不提到腾讯Qzone的lightbox相册,它就是这样做的。它能在图片没有加载完全的时候就居中放大图片,速度与优雅基本兼得。不过它仍然难以避免blog插入的外链图片的问题,也只能按传统的方式加载完毕才能展示。
三、javascript通过占位方式获取图片头部数据的尺寸
十多年的上网经验告诉我:浏览器在加载图片的时候你会看到图片会先占用一块地然后才慢慢加载完毕,并且这里大部分的图片都是没有预设width与height属性的,因为浏览器能够获取图片的头部数据。基于此,只需要使用javascript定时侦测图片的尺寸状态便可得知图片尺寸就绪的状态。
实现代码:
1 <script> 2 function getID(id){ 3 return document.getElementById(id); 4 } 5 6 var center = getID("center"); 7 var btn = getID("btn"); 8 var cur = 0; 9 var arr = ["http://www.miaov.com/miaov_demo/miaov-demo-2/img/image1.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image10.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image2.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image3.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image4.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image5.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image6.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image7.j 10 pg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image8.jpg","http://www.miaov.com/miaov_demo/miaov-demo-2/img/image9.jpg"]; 11 12 // 图片预加载方法 13 function preloading(imgUrl,callback){ 14 var newImg = new Image(); 15 newImg.src = imgUrl; 16 if (newImg.complete) { 17 callback(newImg); 18 } 19 else { 20 newImg.onload = function () { 21 callback(newImg); 22 newImg.onload = null; 23 }; 24 }; 25 26 var width = newImg.offsetWidth; 27 var height = newImg.offsetHeight; 28 var check = function(){ // 侦听图片的头信息返回的宽、高度 29 if(newImg.width !== width || newImg.height !== height){ // 如果宽、高度与初始不相等(相当于已获取到宽、高度) 30 callback(newImg); 31 clearInterval(intervalId); 32 newImg.onload = null; 33 } 34 } 35 var intervalId = setInterval(check, 150); 36 }; 37 38 function showImg(imgObj){ 39 var _w = imgObj.width; 40 var _h = imgObj.height; 41 center.innerHTML = ""; 42 miaovStartMove(center,{width:_w, height:_h},MIAOV_MOVE_TYPE.BUFFER, 43 function(){ 44 imgObj.style.opacity = 0; 45 center.appendChild(imgObj); 46 miaovStartMove(imgObj,{opacity:100},MIAOV_MOVE_TYPE.BUFFER); 47 } 48 ); 49 } 50 51 btn.onclick = function(){ 52 cur++; 53 if(cur >= arr.length){ 54 cur=0; 55 } 56 preloading(arr[cur], showImg); 57 } 58 59 preloading(arr[0],showImg); 60 61 // 运动 62 function css(obj, attr, value){ 63 if(arguments.length == 2){ 64 var sCur=obj.currentStyle?obj.currentStyle[attr]:document.defaultView.getComputedStyle(obj, false)[attr]; 65 if(attr=='opacity') { 66 return parseInt(parseFloat(sCur)*100); 67 } 68 else{ 69 return parseInt(sCur); 70 } 71 } 72 else if(arguments.length==3) 73 switch(attr){ 74 case 'width': 75 case 'height': 76 case 'paddingLeft': 77 case 'paddingTop': 78 case 'paddingRight': 79 case 'paddingBottom': 80 value=Math.max(value,0); 81 case 'left': 82 case 'top': 83 case 'marginLeft': 84 case 'marginTop': 85 case 'marginRight': 86 case 'marginBottom': 87 obj.style[attr]=value+'px'; 88 break; 89 case 'opacity': 90 obj.style.filter="alpha(opacity:"+value+")"; 91 obj.style.opacity=value/100; 92 break; 93 default: 94 obj.style[attr]=value; 95 } 96 return function (attr_in, value_in){css(obj, attr_in, value_in)}; 97 } 98 99 MIAOV_MOVE_TYPE={ 100 BUFFER: 1, 101 FLEX: 2, 102 FAST: 3, 103 SLOW: 4, 104 NORMAL: 5 105 }; 106 function miaovStartMove(obj, oTarget, iType, fnCallBack, fnDuring){ 107 var fnMove=null; 108 if(obj.timer){ 109 clearInterval(obj.timer); 110 } 111 112 switch(iType){ 113 case MIAOV_MOVE_TYPE.BUFFER: 114 fnMove = miaovDoMoveBuffer; 115 break; 116 case MIAOV_MOVE_TYPE.FLEX: 117 fnMove = miaovDoMoveFlex; 118 break; 119 } 120 121 obj.timer=setInterval(function (){ 122 fnMove(obj, oTarget, fnCallBack, fnDuring); 123 124 var now=(new Date()).getTime(); 125 obj.lastMove=now; 126 }, 30); 127 128 if(!obj.lastMove){ 129 obj.lastMove = 0; 130 } 131 132 var now = (new Date()).getTime(); 133 if(now - obj.lastMove > 30){ 134 fnMove(obj, oTarget, fnCallBack, fnDuring); 135 var now = (new Date()).getTime(); 136 obj.lastMove = now; 137 } 138 } 139 140 function miaovDoMoveBuffer(obj, oTarget, fnCallBack, fnDuring){ 141 var bStop = true; 142 var attr = ''; 143 var speed = 0; 144 var cur = 0; 145 146 for(attr in oTarget){ 147 oTarget[attr]=parseInt(oTarget[attr]); 148 cur=css(obj, attr); 149 if(oTarget[attr]!=cur){ 150 bStop=false; 151 speed=(oTarget[attr]-cur)/5; 152 speed=speed>0?Math.ceil(speed):Math.floor(speed); 153 css(obj, attr, cur+speed); 154 } 155 } 156 157 if(fnDuring)fnDuring.call(obj); 158 if(bStop){ 159 clearInterval(obj.timer); 160 obj.timer = null; 161 if(fnCallBack)fnCallBack.call(obj); 162 } 163 } 164 165 function miaovDoMoveFlex(obj, oTarget, fnCallBack, fnDuring){ 166 var bStop = true; 167 var attr = ''; 168 var speed = 0; 169 var cur = 0; 170 171 for(attr in oTarget){ 172 if(!obj.oSpeed)obj.oSpeed = {}; 173 if(!obj.oSpeed[attr])obj.oSpeed[attr]=0; 174 cur=css(obj, attr); 175 if(Math.abs(oTarget[attr]-cur)>=1 || Math.abs(obj.oSpeed[attr])>=1){ 176 bStop=false; 177 obj.oSpeed[attr]+=(oTarget[attr]-cur)/5; 178 obj.oSpeed[attr]*=0.7; 179 css(obj, attr, cur+obj.oSpeed[attr]); 180 } 181 } 182 183 if(fnDuring)fnDuring.call(obj); 184 185 if(bStop){ 186 clearInterval(obj.timer); 187 obj.timer=null; 188 if(fnCallBack)fnCallBack.call(obj); 189 } 190 } 191 192 function stopMove(obj){ 193 clearInterval(obj.timer); 194 } 195 </script>