模仿【http://www.otomate.jp/ghp/fd/】的图片预加载所写。该页使用jQuery,这里使用原生javascript。
在ie6,ie8,FF,Chrome,Opera下测试通过。
过程:
1、在DOM树加载完毕时,将页面内所有图片(img标签,css中的背景图)的地址push进一个数组。
2、用image图片加载完成触发的load事件进行回调,显示当前进度。【已加载完图片数/总图片数】
3、图片全部加载完毕,进行之后的处理。(如上述url页所示,将遮罩层移除)
关键点:
javascript通常采用非阻塞式(异步)编程,故而无法顺次加载图片。
因此必须在每张图片加载完后触发一个回调函数,在回调函数中判断是否全部加载完毕。
相关代码步骤:
1、DOM树加载完毕的事件(jQuery的docuiment ready)
window.onload会在所有资源加载完毕后触发,故而不能使用。
大部分现代浏览器支持DOMContentLoaded事件【webkit525版本以下(safari 3.1以下)不支持,这里不作考虑】;
IE支持readystatechange事件,监听document.readyState属性为【interactive】或【complete】时即可认为加载完毕。
相关代码如下,以《JS高级程序设计》为参考,并作了处理防止重复判断是IE还是现代浏览器。
1 CCC.documentReady = function(f){ 2 if( document.addEventListener ) { 3 CCC.documentReady = function(func){ 4 document.addEventListener('DOMContentLoaded', function(){ 5 document.removeEventListener('DOMContentLoaded', arguments.callee); 6 func(); 7 }, false); 8 }; 9 } else { 10 CCC.documentReady = function(func){ 11 document.attachEvent('onreadystatechange', function(){ 12 if (document.readyState == 'interactive' || document.readyState == 'complete') { 13 document.detachEvent('onreadystatechange', arguments.callee); 14 func(); 15 } 16 }); 17 }; 18 } 19 CCC.documentReady(f); 20 };
2、获取图片url
getStyle为一个获取计算后样式的方法,做了兼容。
各浏览器获取到的background-image属性,格式为【url(...)】,可能包含双引号【url("...")】,因此正则表达式需要考虑到这些情况。
bg.replace(/url("?([^"]+)"?)/, '$1');
var all = document.body.getElementsByTagName('*'); var imgUrls = []; for(var i = 0, len = all.length; i < len; i++) { if(all[i].tagName.toLowerCase() == 'img') { if(all[i].src) { imgUrls.push(all[i].src); } } else { var bg = _(all[i]).getStyle('background-image'); if(/url/.test(bg)) { bg = bg.replace(/url("?([^"]+)"?)/, '$1'); imgUrls.push(bg); } } }
3、preload预加载函数
通过对Image对象设置src属性来加载图片。
如在浏览器中已有缓存,则直接回调;否则添加onload事件处理函数,异步回调。
complete为当前已加载完毕的图片数。
function preload(arr, callback){ var complete = 0; for(var i = 0, len = arr.length; i < len; i++) { var img = new Image(); img.src = arr[i];; if(img.complete) { /* 已缓存 */ callback(++complete, len); continue; } img.onload = function(){ callback(++complete, len); }; } }
4、使用preload函数
在回调方法中,使用一个input标签显示当前进度;
当全部加载完毕(通过complete >= len来判断),进行最后的处理。这里仅仅是简单的alert。
preload(imgUrls, function(complete, len){ if(complete >= len) { progress.value = '100%'; imgUrls = null; alert('complete'); return; } progress.value = parseInt(complete * 100 / len) + '%'; });