再谈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 相关文章推荐
优化JavaScript脚本的性能的几个注意事项
Dec 22 Javascript
jquery 入门教程 [翻译] 推荐
Aug 17 Javascript
IE下使用cloneNode注意事项分享
Nov 22 Javascript
DWZ刷新dialog解决方法
Mar 03 Javascript
JavaScript学习笔记(三):JavaScript也有入口Main函数
Sep 12 Javascript
jQuery学习笔记之Ajax用法实例详解
Dec 01 Javascript
JavaScript判断数组重复内容的两种方法(推荐)
Jun 06 Javascript
node.js发送邮件email的方法详解
Jan 06 Javascript
详解vue slot插槽的使用方法
Jun 13 Javascript
解决vue中post方式提交数据后台无法接收的问题
Aug 11 Javascript
vue watch深度监听对象实现数据联动效果
Aug 16 Javascript
从零开始在vue-cli4配置自适应vw布局的实现
Jun 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
php smarty模板引擎的6个小技巧
2014/04/24 PHP
PHP输出英文时间日期的安全方法(RFC 1123格式)
2014/06/13 PHP
smarty中js的调用方法示例
2014/10/27 PHP
Laravel实现用户注册和登录
2015/01/23 PHP
Zend Framework教程之Loader以及PluginLoader用法详解
2016/03/09 PHP
PHP实现bitmap位图排序与求交集的方法
2016/07/28 PHP
浅谈Coreseek、Sphinx-for-chinaese、Sphinx+Scws的区别
2016/12/15 PHP
YII2框架使用控制台命令的方法分析
2020/03/18 PHP
input按钮的事件处理大全
2010/12/10 Javascript
JS自定义功能函数实现动态添加网址参数修改网址参数值
2013/08/02 Javascript
Javascript核心读书有感之表达式和运算符
2015/02/11 Javascript
ajax+jQuery实现级联显示地址的方法
2015/05/06 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
浅谈JavaScript 函数参数传递到底是值传递还是引用传递
2016/08/23 Javascript
微信小程序 引入es6 promise
2017/04/12 Javascript
jQuery实现切换隐藏与显示同时切换图标功能
2017/10/29 jQuery
vue 插槽简介及使用示例
2020/11/19 Vue.js
Vue组件生命周期运行原理解析
2020/11/25 Vue.js
Python批量重命名同一文件夹下文件的方法
2015/05/25 Python
Django 多语言教程的实现(i18n)
2018/07/07 Python
Python多进程写入同一文件的方法
2019/01/14 Python
Python 绘制酷炫的三维图步骤详解
2019/07/12 Python
python3实现mysql导出excel的方法
2019/07/31 Python
Django框架序列化与反序列化操作详解
2019/11/01 Python
Python用5行代码实现批量抠图的示例代码
2020/04/14 Python
Python虚拟环境的创建和使用详解
2020/09/07 Python
celery在python爬虫中定时操作实例讲解
2020/11/27 Python
python爬虫爬取某网站视频的示例代码
2021/02/20 Python
CSS3实现div从下往上滑入滑出效果示例
2020/04/28 HTML / CSS
html5 canvas绘制矩形和圆形的实例代码
2016/06/16 HTML / CSS
社区健康教育工作方案
2014/06/03 职场文书
营业员岗位职责
2015/02/11 职场文书
毕业实习单位意见
2015/06/04 职场文书
再读《皇帝的新衣》的读后感悟!
2019/08/07 职场文书
MySQL系列之三 基础篇
2021/07/02 MySQL
windows server 2016 域环境搭建的方法步骤(图文)
2022/06/25 Servers