再谈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中使用正则匹配多条,且获取每条中的分组数据
Nov 30 Javascript
jQuery 选择器项目实例分析及实现代码
Dec 28 Javascript
JavaScript操纵窗口的方法小结
Jun 28 Javascript
jQuery实现的原图对比窗帘效果
Jun 15 Javascript
jQuery遍历页面所有CheckBox查看是否被选中的方法
Apr 14 Javascript
基于React.js实现原生js拖拽效果引发的思考
Mar 30 Javascript
基于JS代码实现导航条弹出式悬浮菜单
Jun 17 Javascript
AngularJS基础 ng-readonly 指令简单示例
Aug 02 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
Sep 26 Javascript
jQuery居中元素scrollleft计算方法示例
Jan 16 Javascript
vue使用element-ui的el-input监听不了回车事件的解决方法
Jan 12 Javascript
详解Element-UI中上传的文件前端处理
Aug 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
如何过滤高亮显示非法字符
2006/10/09 PHP
php include,include_once,require,require_once
2008/09/05 PHP
php面向对象全攻略 (五) 封装性
2009/09/30 PHP
php数组函数序列之end() - 移动数组内部指针到最后一个元素,并返回该元素的值
2011/10/31 PHP
CodeIgniter框架中_remap()使用方法2例
2014/03/10 PHP
BOOM vs RR BO3 第一场2.13
2021/03/10 DOTA
jquery事件机制扩展插件 jquery鼠标右键事件。
2011/12/26 Javascript
深入探讨JavaScript String对象
2015/03/09 Javascript
介绍一个简单的JavaScript类框架
2015/06/24 Javascript
JavaScript setTimeout使用闭包功能实现定时打印数值
2015/12/18 Javascript
JavaScript模版引擎的基本实现方法浅析
2016/02/15 Javascript
Javascript实现代码折叠功能
2016/08/25 Javascript
easyui form validate总是返回false的原因及解决方法
2016/11/07 Javascript
JS实现颜色动态淡化效果
2017/03/06 Javascript
JS控件bootstrap datepicker使用方法详解
2017/03/25 Javascript
node中使用es5/6以及支持性与性能对比
2017/08/11 Javascript
解决iview多表头动态更改列元素发生的错误的方法
2018/11/02 Javascript
原生js通过一行代码实现简易轮播图
2019/06/05 Javascript
vue中的过滤器实例代码详解
2019/06/06 Javascript
详解JavaScript修改注册表的方法
2020/01/05 Javascript
vue中 v-for循环的用法详解
2020/02/19 Javascript
Jquery 获取相同NAME 或者id删除行操作
2020/08/24 jQuery
[49:27]2018DOTA2亚洲邀请赛 4.4 淘汰赛 TNC vs VG 第一场
2018/04/05 DOTA
用pandas按列合并两个文件的实例
2018/04/12 Python
使用Python实现 学生学籍管理系统
2019/11/26 Python
详解Python中Pyyaml模块的使用
2020/10/08 Python
GANT葡萄牙官方商店:拥有美国运动服传统的生活方式品牌
2018/10/18 全球购物
Harman Audio官方商店:购买JBL、Harman Kardon、Infinity和AKG
2019/12/05 全球购物
桥梁工程专业求职信
2014/04/21 职场文书
环保专项行动方案
2014/05/12 职场文书
行政部经理助理岗位职责
2014/06/15 职场文书
优秀教师先进个人事迹材料
2014/08/31 职场文书
质量在我心中演讲稿
2014/09/02 职场文书
辞职信如何写
2015/02/27 职场文书
单位考核鉴定意见
2015/06/05 职场文书
DIV CSS实现网页背景半透明效果
2021/12/06 HTML / CSS