再谈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 相关文章推荐
在textarea文本域中显示HTML代码的方法
Mar 06 Javascript
深入理解JavaScript定时机制
Oct 29 Javascript
关于jquery性能最佳实践的讨论,与求教
Mar 30 Javascript
Node.js中的process.nextTick使用实例
Jun 25 Javascript
理解JavaScript中worker事件api
Dec 25 Javascript
JQuery中解决重复动画的方法
Oct 17 Javascript
jQuery+pjax简单示例汇总
Apr 21 jQuery
JavaScript之Date_动力节点Java学院整理
Jun 28 Javascript
详解关于react-redux中的connect用法介绍及原理解析
Sep 11 Javascript
JS使用栈判断给定字符串是否是回文算法示例
Mar 04 Javascript
微信小程序如何调用新闻接口实现列表循环
Jul 02 Javascript
webpack HappyPack实战详解
Oct 08 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
PHP4在WinXP下IIS和Apache2服务器上的安装实例
2006/10/09 PHP
PHP限制HTML内容中图片必须是本站的方法
2015/06/16 PHP
浅析Yii2集成富文本编辑器redactor实例教程
2016/04/25 PHP
PHP Filter过滤器全面解析
2016/08/09 PHP
JS 文件大小判断的实现代码
2010/04/07 Javascript
Array.prototype 的泛型应用分析
2010/04/30 Javascript
javascript检测浏览器flash版本的实现代码
2011/12/06 Javascript
jQuery Tools Dateinput使用介绍
2012/07/14 Javascript
Jquery 获取对象的几种方式介绍
2014/01/17 Javascript
javascript实现单击和双击并存的方法
2014/12/13 Javascript
javascript中parseInt()函数的定义和用法分析
2014/12/20 Javascript
JavaScript静态类型检查工具FLOW简介
2015/01/06 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
利用jQuery实现一个简单的表格上下翻页效果
2017/03/14 Javascript
关于Ajax的原理以及代码封装详解
2017/09/08 Javascript
mockjs,json-server一起搭建前端通用的数据模拟框架教程
2017/12/18 Javascript
Angular2之二级路由详解
2018/08/31 Javascript
vue项目打包上传github并制作预览链接(pages)
2019/04/19 Javascript
[45:59]完美世界DOTA2联赛PWL S2 FTD vs GXR 第二场 11.22
2020/11/24 DOTA
Python中if __name__ == '__main__'作用解析
2015/06/29 Python
用Python编写简单的微博爬虫
2016/03/04 Python
浅谈pandas筛选出表中满足另一个表所有条件的数据方法
2019/02/08 Python
Python 函数返回值的示例代码
2019/03/11 Python
pandas 数据结构之Series的使用方法
2019/06/21 Python
python爬虫 爬取超清壁纸代码实例
2019/08/16 Python
Python类的动态绑定实现原理
2020/03/21 Python
tensorflow下的图片标准化函数per_image_standardization用法
2020/06/30 Python
用html5实现语音搜索框的方法
2014/03/18 HTML / CSS
Under Armour安德玛意大利官网:美国高端运动科技品牌
2020/01/16 全球购物
希腊品牌鞋类销售网站:epapoutsia.gr
2020/03/18 全球购物
Java语言的优势
2015/01/10 面试题
个人自荐书
2013/12/20 职场文书
民生工作实施方案
2014/05/31 职场文书
学生个人总结范文
2015/02/15 职场文书
解析Redis Cluster原理
2021/06/21 Redis
python如何读取和存储dict()与.json格式文件
2022/06/25 Python