再谈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 相关文章推荐
juqery 学习之五 文档处理 插入
Feb 11 Javascript
JQuery 选择器、过滤器介绍
Feb 14 Javascript
JavaScript全排列的六种算法 具体实现
Jun 29 Javascript
javascript中的取反再取反~~没有意义
Apr 06 Javascript
Bootstrap实现弹性搜索框
Jul 11 Javascript
JavaScript重定向URL参数的两种方法小结
Oct 19 Javascript
用js实现每隔一秒刷新时间的实例(含年月日时分秒)
Oct 25 Javascript
JS删除数组里的某个元素方法
Feb 03 Javascript
详解使用React.memo()来优化函数组件的性能
Mar 19 Javascript
JavaScript forEach中return失效问题解决方案
Jun 01 Javascript
Angular+ionic实现折叠展开效果的示例代码
Jul 29 Javascript
动态规划之使用备忘录来改进Javascript函数
Apr 07 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实现的生成静态HTML速度快类库
2007/03/31 PHP
php 应用程序安全防范技术研究
2009/09/25 PHP
PHP动态分页函数,PHP开发分页必备啦
2011/11/07 PHP
php过滤所有的空白字符(空格、全角空格、换行等)
2015/10/27 PHP
PHP addslashes()函数讲解
2019/02/03 PHP
Laravel框架处理用户的请求操作详解
2019/12/20 PHP
lib.utf.js
2007/08/21 Javascript
Dojo 学习要点
2010/09/03 Javascript
js的2种继承方式详解
2014/03/04 Javascript
Javascript中call与apply的学习笔记
2014/09/22 Javascript
js实现动态加载脚本的方法实例汇总
2015/11/02 Javascript
apply和call方法定义及apply和call方法的区别
2015/11/15 Javascript
jQuery遍历DOM元素与节点方法详解
2016/04/14 Javascript
jQuery之简单的表单验证实例
2016/07/07 Javascript
深入理解jQuery layui分页控件的使用
2016/08/17 Javascript
nodejs实例解析(输出hello world)
2017/01/03 NodeJs
一个可复用的vue分页组件
2017/05/15 Javascript
webpack项目调试以及独立打包配置文件的方法
2018/02/28 Javascript
微信小程序实现点击按钮后修改颜色
2019/12/05 Javascript
javaScript 实现重复输出给定的字符串的常用方法小结
2020/02/20 Javascript
javascript 设计模式之享元模式原理与应用详解
2020/04/08 Javascript
ES5 模拟 ES6 的 Symbol 实现私有成员功能示例
2020/05/06 Javascript
vue实现移动端项目多行文本溢出省略
2020/07/29 Javascript
详解JavaScript 高阶函数
2020/09/14 Javascript
django manage.py扩展自定义命令方法
2018/05/27 Python
详解Django中类视图使用装饰器的方式
2018/08/12 Python
Python设计模式之享元模式原理与用法实例分析
2019/01/11 Python
Python Pexpect库的简单使用方法
2019/01/29 Python
python列表每个元素同增同减和列表元素去空格的实例
2019/07/20 Python
Python Django简单实现session登录注销过程详解
2019/08/06 Python
实习护士自荐信
2014/06/21 职场文书
小学生我的梦想演讲稿
2014/08/21 职场文书
2015年酒店工作总结
2015/04/28 职场文书
管理失职检讨书范文
2015/05/05 职场文书
演讲稿之感恩老师(三篇范文)
2019/09/06 职场文书
Redis+Lua脚本实现计数器接口防刷功能(升级版)
2022/02/12 Redis