javascript通过文件头信息获取图片宽高

由于javascript无法获取img文件头数据,必须等待其加载完毕后才能获取真实的大小,所以lightbox类效果为了让图片居中显示,导致其速度体验要比直接输出的差很多。而本文通过一个巧妙的方法让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 () { varlist = [], 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(); }; // 检测图片是否已经占位// 事实上检测offsetWidth能兼容所有目前参与测试的浏览器// 为了防止本函数运行前图片已经处于加载进程导致检测失败,检测初始图像的面积仍可以得知其就绪状态 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); img = div = null; }; // 将检测图片是否占位的函数加入定时器列队定期执行// 同一图片只加入一个检测器// 无论何时只允许出现一个定时器,减少浏览器性能损耗 !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 

(通过测试的浏览器:Chrome、Firefox、Safari、Opera、IE6、IE7、IE8)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值