再谈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 相关文章推荐
js 获取和设置css3 属性值的实现方法
May 06 Javascript
Javascript学习笔记之 函数篇(二) : this 的工作机制
Jun 24 Javascript
JavaScript中document.forms[0]与getElementByName区别
Jan 21 Javascript
seajs加载jquery时提示$ is not a function该怎么解决
Oct 23 Javascript
原生javascript实现自动更新的时间日期
Feb 12 Javascript
JQuery 传送中文乱码问题的简单解决办法
May 24 Javascript
完美JQuery图片切换效果的简单实现
Jul 21 Javascript
vue.js删除动态绑定的radio的指定项
Jun 02 Javascript
关于使用js算总价的问题
Jun 23 Javascript
微信小程序上传帖子的实例代码(含有文字图片的微信验证)
Jul 11 Javascript
node脚手架搭建服务器实现token验证的方法
Jan 20 Javascript
Vite + React从零开始搭建一个开源组件库
Jun 25 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 数组字符串搜索array_search技巧
2016/07/05 PHP
PHP中时间加减函数strtotime用法分析
2017/04/26 PHP
jQuery选择器的工作原理和优化分析
2011/07/25 Javascript
关于JavaScript中string 的replace
2013/04/12 Javascript
原生javascript实现简单的datagrid数据表格
2015/01/02 Javascript
javascript实现图片自动和可控的轮播切换特效
2015/04/13 Javascript
jQuery控制DIV层实现由大到小,由远及近动画变化效果
2015/10/09 Javascript
AngularJS转换响应内容
2016/01/27 Javascript
js基于myFocus实现轮播图效果
2017/02/14 Javascript
微信小程序页面开发注意事项整理
2017/05/18 Javascript
ionic3+Angular4实现接口请求及本地json文件读取示例
2017/10/11 Javascript
vue 开发一个按钮组件的示例代码
2018/03/27 Javascript
layui的数据表格+springmvc实现搜索功能的例子
2019/09/28 Javascript
Jquery+AJAX实现无刷新上传并重命名文件操作示例【PHP后台接收】
2020/05/29 jQuery
NodeJS配置CORS实现过程详解
2020/12/02 NodeJs
[01:20]PWL开团时刻DAY9——听说潮汐没用?
2020/11/10 DOTA
Python删除指定目录下过期文件的2个脚本分享
2014/04/10 Python
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
python如何让类支持比较运算
2018/03/20 Python
jupyter notebook引用from pyecharts.charts import Bar运行报错
2020/04/23 Python
利用python画出折线图
2018/07/26 Python
Python GUI库PyQt5样式QSS子控件介绍
2020/02/25 Python
Python requests模块安装及使用教程图解
2020/06/30 Python
Python Request类源码实现方法及原理解析
2020/08/17 Python
Html5之自定义属性(data-,dataset)
2019/11/19 HTML / CSS
DOUGLAS波兰:在线销售香水和化妆品
2020/07/05 全球购物
斯洛伐克电子产品购物网站:DATART
2020/04/05 全球购物
颇特女士:NET-A-PORTER(直邮中国)
2020/07/11 全球购物
"引用"与指针的区别是什么
2016/09/07 面试题
文明学生标兵事迹
2014/01/21 职场文书
2014学雷锋活动心得体会
2014/03/10 职场文书
帮一个朋友写的求职信
2014/08/09 职场文书
计生个人工作总结
2015/02/28 职场文书
创业计划书之儿童理发店
2019/09/27 职场文书
Redis实现订单自动过期功能的示例代码
2021/05/08 Redis
怎么禁用Windows 11快照布局? win11不使用快照布局的技巧
2021/11/21 数码科技