再谈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表数据排序 sort table data
Feb 18 Javascript
JS在IE和FF下attachEvent,addEventListener学习笔记
Nov 26 Javascript
基于jQuery的history历史记录插件
Dec 11 Javascript
使用javascript:将其它类型值转换成布尔类型值的解决方法详解
May 07 Javascript
通过正则表达式实现表单验证是否为中文
Feb 18 Javascript
对比分析AngularJS中的$http.post与jQuery.post的区别
Feb 27 Javascript
学习JavaScript编程语言的8张思维导图分享
Mar 27 Javascript
Bootstrap幻灯片轮播图支持触屏左右手势滑动的实现方法
Oct 13 Javascript
JS文件中加载jquery.js的实例代码
May 05 jQuery
通过js给网页加上水印背景实例
Jun 17 Javascript
vue在App.vue文件中监听路由变化刷新页面操作
Aug 14 Javascript
聊聊vue 中的v-on参数问题
Jan 29 Vue.js
在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
15个小时----从修改程序到自己些程序
2006/10/09 PHP
如何判断php数组的维度
2013/06/10 PHP
ThinkPHP令牌验证实例
2014/06/18 PHP
CodeIgniter错误mysql_connect(): No such file or directory解决方法
2014/09/06 PHP
php gd等比例缩放压缩图片函数
2016/06/12 PHP
什么是PHP文件?如何打开PHP文件?
2017/06/27 PHP
php大小写转换函数(strtolower、strtoupper)用法介绍
2017/11/17 PHP
PHP针对redis常用操作实例详解
2019/08/17 PHP
JS 用6N±1法求素数 实例教程
2009/10/20 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
js图片卷帘门导航菜单特效代码分享
2015/09/10 Javascript
jQuery右下角悬浮广告实例
2016/10/17 Javascript
深入浅出es6模板字符串
2017/08/26 Javascript
JS用最简单的方法实现四舍五入
2019/08/27 Javascript
uniapp微信小程序:key失效的解决方法
2021/01/20 Javascript
vue+echarts实现中国地图流动效果(步骤详解)
2021/01/27 Vue.js
[57:53]DOTA2上海特级锦标赛主赛事日 - 2 败者组第二轮#3OG VS VP
2016/03/03 DOTA
python实现数通设备tftp备份配置文件示例
2014/04/02 Python
Python Web开发模板引擎优缺点总结
2014/05/06 Python
Python实现的凯撒密码算法示例
2018/04/12 Python
Python实现通过继承覆盖方法示例
2018/07/02 Python
python中使用print输出中文的方法
2018/07/16 Python
python实现简单银行管理系统
2019/10/25 Python
python中利用matplotlib读取灰度图的例子
2019/12/07 Python
python实现布隆过滤器及原理解析
2019/12/08 Python
Java byte数组操纵方式代码实例解析
2020/07/22 Python
意大利简约的休闲品牌:Aspesi
2018/02/08 全球购物
应届大专毕业生自我鉴定
2014/04/08 职场文书
领导批评与自我批评范文
2014/10/16 职场文书
房屋产权证明书
2015/06/19 职场文书
《生物入侵者》教学反思
2016/02/16 职场文书
抖音短视频(douyin)去水印工具的实现代码
2021/03/30 Javascript
Python基础之字符串格式化详解
2021/04/21 Python
使用logback实现按自己的需求打印日志到自定义的文件里
2021/08/30 Java/Android
JPA 通过Specification如何实现复杂查询
2021/11/23 Java/Android
对象析构函数__del__在Python中何时使用
2022/03/22 Python