再谈javascript图片预加载技术(详细演示)


Posted in Javascript onMarch 12, 2011

而本文所提到的预加载技术主要是让javascript快速获取图片头部数据的尺寸。

一段典型的使用预加载获取图片大小的例子:

var imgLoad = function (url, callback) { 
var img = new Image(); 
img.src = url; 
if (img.complete) { 
callback(img.width, img.height); 
} else { 
img.onload = function () { 
callback(img.width, img.height); 
img.onload = null; 
}; 
}; 
};

可以看到使用onload的方式必须等待图片加载完毕,其速度不敢恭维。
web应用程序区别于桌面应用程序,响应速度才是最好的用户体验。如果想要速度与优雅兼得,那就必须提前获得图片尺寸,如何在图片没有加载完毕就能获取图片尺寸?
十多年的上网经验告诉我:浏览器在加载图片的时候你会看到图片会先占用一块地然后才慢慢加载完毕,并且这里大部分的图片都是没有预设width与height属性的,因为浏览器能够获取图片的头部数据。基于此,只需要使用javascript定时侦测图片的尺寸状态便可得知图片尺寸就绪的状态。
实现代码(2011-03-11更新):
2011-03-12 更新:
只使用一定时器,优化性能
/*! 
* img ready v0.3 
* http://www.planeart.cn/?p=1121 
* TangBin - MIT Licensed 
*/ 
// 图片头数据加载就绪事件 
// @param {String} 图片路径 
// @param {Function} 获取尺寸的回调函数 (参数1接收width;参数2接收height) 
// @param {Function} 加载错误的回调函数 (可选) 
(function () { 
var list = [], intervalId = null, 
tick = function () { 
var i = 0; 
for (; i < list.length; i++) { 
list[i].end ? list.splice(i--, 1) : list[i](); 
}; 
!list.length && stop(); 
}, 
stop = function () { 
clearInterval(intervalId); 
intervalId = null; 
}; 
this.imgReady = function (url, callback, error) { 
var check, end, width, height, offsetWidth, offsetHeight, div, 
accuracy = 1024, 
doc = document, 
container = doc.body || doc.getElementsByTagName('head')[0], 
img = new Image(); 
img.src = url; 
if (!callback) return img; 
// 如果图片被缓存,则直接返回缓存数据 
if (img.complete) return callback(img.width, img.height); 
// 向页面插入隐秘图像,用来监听图片是否占位 
div = doc.createElement('div'); 
div.style.cssText = 'visibility:hidden;position:absolute;left:0;top:0;width:1px;height:1px;overflow:hidden'; 
div.appendChild(img) 
container.appendChild(div); 
width = img.offsetWidth; 
height = img.offsetHeight; 
// 完全加载完毕的事件 
img.onload = function () { 
end(); 
callback(img.width, img.height); 
}; 
// 加载错误后的事件 
img.onerror = function () { 
end(); 
error && error(); 
}; 
// 检测图片是否已经占位 
check = function () { 
offsetWidth = img.offsetWidth; 
offsetHeight = img.offsetHeight; 
if (offsetWidth !== width || offsetHeight !== height || offsetWidth * offsetHeight > accuracy) { 
end(); 
callback(offsetWidth, offsetHeight); 
}; 
}; 
check.url = url; 
// 操作结束后进行清理 
// 删除元素与事件,避免IE内存泄漏 
end = function () { 
check.end = true; 
img.onload = img.onerror = null; 
div.innerHTML = ''; 
div.parentNode.removeChild(div); 
}; 
// 将检测图片是否占位的函数加入定时器列队定期执行 
// 同一图片只加入一个检测器 
// 无论何时只允许出现一个定时器,减少浏览器性能损耗 
!check.end && check(); 
for (var i = 0; i < list.length; i ++) { 
if (list[i].url === url) return; 
}; 
if (!check.end) { 
list.push(check); 
if (!intervalId) intervalId = setInterval(tick, 150); 
}; 
}; 
})();

是不是很简单?这样的方式获取摄影级别照片尺寸的速度往往是onload方式的几十多倍,而对于web普通(800×600内)浏览级别的图片能达到秒杀效果。
好了,请观赏令人愉悦的 DEMO : http://demo.3water.com/js/2011/imgready/
(通过测试的浏览器:Chrome、Firefox、Safari、Opera、IE6、IE7、IE8)
来自:: 唐斌
Javascript 相关文章推荐
mouse_on_title.js
Aug 25 Javascript
js资料prototype 属性
Mar 13 Javascript
textContent在Firefox下与innerText等效的属性
May 12 Javascript
判断复选框是否被选中的两种方法
Jun 04 Javascript
jQuery切换所有复选框选中状态的方法
Jul 02 Javascript
javascript 实现动态侧边栏实例详解
Nov 11 Javascript
js轮播图透明度切换(带上下页和底部圆点切换)
Apr 27 Javascript
Vue数组更新及过滤排序功能
Aug 10 Javascript
vue mint-ui tabbar变组件使用
May 04 Javascript
详解vue项目接入微信JSSDK的坑
Dec 14 Javascript
layui动态渲染生成select的option值方法
Sep 23 Javascript
JavaScript实现音乐导航效果
Nov 19 Javascript
在jQuery1.5中使用deferred对象 着放大镜看Promise
Mar 12 #Javascript
使用jquery插件实现图片延迟加载技术详细说明
Mar 12 #Javascript
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
Mar 12 #Javascript
javascript textarea光标定位方法(兼容IE和FF)
Mar 12 #Javascript
JavaScript全局函数使用简单说明
Mar 11 #Javascript
js+css使DIV始终居于屏幕中间 左下 左上 右上 右下的代码集合
Mar 10 #Javascript
始终在屏幕中间显示Div的代码(css+js)
Mar 10 #Javascript
You might like
php中静态类与静态变量用法的区别分析
2015/01/15 PHP
php将数组存储为文本文件方法汇总
2015/10/28 PHP
[原创]PHP简单开启curl的方法(测试可行)
2016/01/11 PHP
关于跨站脚本攻击问题
2011/12/22 Javascript
js中top/parent/frame概述及案例应用
2013/02/06 Javascript
关于JavaScript与HTML的交互事件
2013/04/12 Javascript
JS获取DropDownList的value值与text值的示例代码
2014/01/07 Javascript
js计算德州扑克牌面值的方法
2015/03/04 Javascript
jquery ajax结合thinkphp的getjson实现跨域的方法
2016/06/06 Javascript
Jquery uploadify 多余的Get请求(404错误)的解决方法
2017/01/26 Javascript
一个有意思的鼠标点击文字特效jquery代码
2017/09/23 jQuery
解决layui中的form表单与button的点击事件冲突问题
2018/08/15 Javascript
微信小程序发送短信验证码完整实例
2019/01/07 Javascript
Vue 动态添加路由及生成菜单的方法示例
2019/06/20 Javascript
Vue动态面包屑功能的实现方法
2019/07/01 Javascript
javascript实现视频弹幕效果(两个版本)
2019/11/28 Javascript
javascript中innerHTML 获取或替换html内容的实现代码
2020/03/17 Javascript
ant design vue导航菜单与路由配置操作
2020/10/28 Javascript
[03:07]DOTA2英雄基础教程 冰霜诅咒极寒幽魂
2013/12/06 DOTA
python Django模板的使用方法(图文)
2013/11/04 Python
Python标准库之sqlite3使用实例
2014/11/25 Python
Python实现统计单词出现的个数
2015/05/28 Python
使用Django的模版来配合字符串翻译工作
2015/07/27 Python
简析Python的闭包和装饰器
2016/02/26 Python
对IPython交互模式下的退出方法详解
2019/02/16 Python
Django 外键的使用方法详解
2019/07/19 Python
python编写计算器功能
2019/10/25 Python
python对指定字符串逆序的6种方法(小结)
2020/04/02 Python
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
英国最大的在线蜡烛商店:Candles Direct
2019/03/26 全球购物
小学教师的自我评价范例
2013/10/31 职场文书
高中语文课后反思
2014/04/27 职场文书
2014年社会实践活动总结范文
2014/04/29 职场文书
私营公司诉讼代理委托书范本
2014/09/13 职场文书
2014年乡镇工作总结
2014/11/21 职场文书
CSS实现单选折叠菜单功能
2021/11/01 HTML / CSS