再谈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 相关文章推荐
兼容IE与firefox火狐的回车事件(js与jquery)
Oct 20 Javascript
Json对象替换字符串占位符实现代码
Nov 17 Javascript
js中通过split函数分割字符串成数组小例子
Sep 21 Javascript
jQuery实现鼠标滚动图片延迟加载效果附源码下载
Jun 28 Javascript
Node.js中文件操作模块File System的详细介绍
Jan 05 Javascript
JQuery 获取Dom元素的实例讲解
Jul 08 jQuery
React中上传图片到七牛的示例代码
Oct 10 Javascript
原生JS封装_new函数实现new关键字的功能
Aug 12 Javascript
3分钟读懂移动端rem使用方法(推荐)
May 06 Javascript
了解Javascript中函数作为对象的魅力
Jun 19 Javascript
微信小程序 this.triggerEvent()的具体使用
Dec 10 Javascript
package.json各个属性说明详解
Mar 11 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
欧美媒体选出10年前最流行的17部动画
2017/01/18 日漫
用PHP和ACCESS写聊天室(四)
2006/10/09 PHP
PHP新手上路(七)
2006/10/09 PHP
php对mongodb的扩展(初出茅庐)
2012/11/11 PHP
在PHP中使用redis
2013/11/04 PHP
php实现cc攻击防御和防止快速刷新页面示例
2014/02/13 PHP
php设置session值和cookies的学习示例
2014/03/21 PHP
js中根据字数截取字符串,不能截断url
2012/01/12 Javascript
js实现同一页面多个不同运动效果的方法
2015/04/10 Javascript
JavaScript模板引擎用法实例
2015/07/10 Javascript
提高jQuery性能优化的技巧
2015/08/03 Javascript
ztree获取选中节点时不能进入可视区域出现BUG如何解决
2015/12/03 Javascript
js编写一个简单的产品放大效果代码
2016/06/27 Javascript
Asp.Net之JS生成分页条的方法
2016/11/23 Javascript
原生js实现鼠标跟随效果
2017/02/28 Javascript
vue webpack实用技巧总结
2018/04/24 Javascript
layui实现左侧菜单点击右侧内容区显示
2019/07/26 Javascript
Vue表单控件数据绑定方法详解
2020/02/05 Javascript
vue自定义指令限制输入框输入值的步骤与完整代码
2020/08/30 Javascript
Python with语句上下文管理器两种实现方法分析
2018/02/09 Python
Python中单例模式总结
2018/02/20 Python
Python合并多个Excel数据的方法
2018/07/16 Python
对Python中plt的画图函数详解
2018/11/07 Python
python定时按日期备份MySQL数据并压缩
2019/04/19 Python
python Jupyter运行时间实例过程解析
2019/12/13 Python
python定义具名元组实例操作
2021/02/28 Python
英国女性运动服品牌:Sweaty Betty
2018/11/08 全球购物
护理工作感言
2014/01/16 职场文书
我的梦想演讲稿500字
2014/08/21 职场文书
委托书格式要求
2015/01/28 职场文书
2015年清明节活动总结
2015/02/09 职场文书
2015年老干部工作总结
2015/04/23 职场文书
2015年餐厅服务员工作总结
2015/04/23 职场文书
土木工程生产实习心得体会
2016/01/22 职场文书
选择比努力更重要?这是长期以来对“努力”的最大误解
2019/07/12 职场文书
MySQL中CURRENT_TIMESTAMP的使用方式
2021/11/27 MySQL