`

再谈javascript图片预加载技术

 
阅读更多

比onload更快获取图片尺寸

文章更新:2011-05-31
lightbox类效果为了让图片居中显示而使用预加载,需要等待完全加载完毕才能显示,体验不佳(如filick相册的全屏效果)。javascript无法获取img文件头数据,真的是这样吗?本文通过一个巧妙的方法让javascript获取它。

这是大部分人使用预加载获取图片大小的例子:

01 var imgLoad = function (url, callback) {
02     var img = new Image();
03  
04     img.src = url;
05     if (img.complete) {
06         callback(img.width, img.height);
07     else {
08         img.onload = function () {
09             callback(img.width, img.height);
10             img.onload = null;
11         };
12     };
13  
14 };

可以看到上面必须等待图片加载完毕才能获取尺寸,其速度不敢恭维,我们需要改进。

web应用程序区别于桌面应用程序,响应速度才是最好的用户体验。如果想要速度与优雅兼得,那就必须提前获得图片尺寸,如何在图片没有加载完毕就能获取图片尺寸?

十多年的上网经验告诉我:浏览器在加载图片的时候你会看到图片会先占用一块地然后才慢慢加载完毕,并且不需要预设width与height属性,因为浏览器能够获取图片的头部数据。基于此,只需要使用javascript定时侦测图片的尺寸状态便可得知图片尺寸就绪的状态。

当然实际中会有一些兼容陷阱,如width与height检测各个浏览器的不一致,还有webkit new Image()建立的图片会受以处在加载进程中同url图片影响,经过反复测试后的最佳处理方式:

 

01 // 更新:
02 // 05.27: 1、保证回调执行顺序:error > ready > load;2、回调函数this指向img本身
03 // 04-02: 1、增加图片完全加载后的回调 2、提高性能
04  
05 /**
06  * 图片头数据加载就绪事件 - 更快获取图片尺寸
07  * @version 2011.05.27
08  * @author  TangBin
09  * @see     http://www.planeart.cn/?p=1121
10  * @param   {String}    图片路径
11  * @param   {Function}  尺寸就绪
12  * @param   {Function}  加载完毕 (可选)
13  * @param   {Function}  加载错误 (可选)
14  * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
15         alert('size ready: width=' + this.width + '; height=' + this.height);
16     });
17  */
18 var imgReady = (function () {
19     var list = [], intervalId = null,
20  
21     // 用来执行队列
22     tick = function () {
23         var i = 0;
24         for (; i < list.length; i++) {
25             list[i].end ? list.splice(i--, 1) : list[i]();
26         };
27         !list.length && stop();
28     },
29  
30     // 停止所有定时器队列
31     stop = function () {
32         clearInterval(intervalId);
33         intervalId = null;
34     };
35  
36     return function (url, ready, load, error) {
37         var onready, width, height, newWidth, newHeight,
38             img = new Image();
39          
40         img.src = url;
41  
42         // 如果图片被缓存,则直接返回缓存数据
43         if (img.complete) {
44             ready.call(img);
45             load && load.call(img);
46             return;
47         };
48          
49         width = img.width;
50         height = img.height;
51          
52         // 加载错误后的事件
53         img.onerror = function () {
54             error && error.call(img);
55             onready.end = true;
56             img = img.onload = img.onerror = null;
57         };
58          
59         // 图片尺寸就绪
60         onready = function () {
61             newWidth = img.width;
62             newHeight = img.height;
63             if (newWidth !== width || newHeight !== height ||
64                 // 如果图片已经在其他地方加载可使用面积检测
65                 newWidth * newHeight > 1024
66             ) {
67                 ready.call(img);
68                 onready.end = true;
69             };
70         };
71         onready();
72          
73         // 完全加载完毕的事件
74         img.onload = function () {
75             // onload在定时器时间差范围内可能比onready快
76             // 这里进行检查并保证onready优先执行
77             !onready.end && onready();
78          
79             load && load.call(img);
80              
81             // IE gif动画会循环执行onload,置空onload即可
82             img = img.onload = img.onerror = null;
83         };
84  
85         // 加入队列中定期执行
86         if (!onready.end) {
87             list.push(onready);
88             // 无论何时只允许出现一个定时器,减少浏览器性能损耗
89             if (intervalId === null) intervalId = setInterval(tick, 40);
90         };
91     };
92 })();

调用例子:

2     alert('size ready: width=' this.width + '; height=' this.height);
3 });

是不是很简单?这样的方式获取摄影级别照片尺寸的速度往往是onload方式的几十多倍,而对于web普通(800×600内)浏览级别的图片能达到秒杀效果。看了这个再回忆一下你见过的web相册,是否绝大部分都可以重构一下呢?好了,请观赏令人愉悦的 DEMO :

http://www.planeart.cn/demo/imgReady/

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

分享到:
评论

相关推荐

    再谈javascript图片预加载技术(详细演示)

    而本文所提到的预加载技术主要是让javascript快速获取图片头部数据的尺寸。一段典型的使用预加载获取图片大小的例子: 代码如下: var imgLoad = function (url, callback) { var img = new Image(); img.src = url; ...

    浅谈vue中使用图片懒加载vue-lazyload插件详细指南

    在Vue.js应用中,为了优化用户体验,特别是在处理大量图片或者网络环境较差时,可以采用图片懒加载技术。本文将详细讲解如何使用`vue-lazyload`插件来实现这一功能。 `vue-lazyload`是一个专门针对Vue.js设计的图片...

    学习JavaScript设计模式之代理模式

    图片预加载是一种常用技术,如果直接给某个img标签节点设置src属性,由于图片过大或者网络不佳,图片的位置往往有段时间会有空白。常见的做法事先用一张loading图片占位,然后异步加载图片,待图片加载完成

    浅谈tudou土豆网首页图片延迟加载的效果

    1. **预加载处理**:首先,将所有需要延迟加载的图片的`src`属性设置为同一张小图(通常是一个占位符或精灵图),而真正的图片URL则存储在图片的`alt`属性中。例如: ```html ``` 2. **事件监听**:通过监听`...

    javascript面试题

    - 使用懒加载技术。 - 图片压缩减小文件大小。 - 采用响应式图像格式(如 WebP)。 - CDN 加速。 **15、你如何理解 HTML 结构的语义化?** 语义化的 HTML 结构意味着使用正确的 HTML 标签来表示内容的意义和结构,...

    0.1秒的价值!浅谈Web前端页面提速问题

    - 对静态资源进行HTTP2 Server Push,预加载用户可能需要的资源。 通过这些策略,可以显著提升Web前端页面的访问速度,减少用户等待时间,从而提供更好的用户体验。优化页面加载速度是一个持续的过程,需要不断...

    浅谈前端网络、JavaScript优化以及开发小技巧

    在JavaScript优化方面,文章提到了图片预加载的策略。在“秋名山活动”中,由于涉及到大量图片的加载,开发者采取了在页面载入时先加载一些通用图片,并在答题阶段预先加载后续页面中的图片,以防止用户访问页面时...

    浅谈网站架构中缓存的应用

    浏览器缓存是最常见的一种,它存储用户的静态资源(如图片、CSS和JavaScript文件),当用户再次访问同一页面时,可以直接从本地加载,无需重新下载。数据库缓存如MySQL的InnoDB Buffer Pool,用于存储数据库表页,...

    简洁个人博客css模板下载_简洁 个人 博客.rar

    4. **性能优化**:优化CSS代码,减少HTTP请求,使用雪碧图或CSS Sprite技术合并小图片,提高页面加载速度。 在实际应用中,下载的“简洁个人博客css模板”可能包含HTML文件、CSS文件、JavaScript文件以及图片资源等...

    APP应用手机网站html模板

    移动设备通常具有较小的屏幕尺寸和触摸交互方式,因此模板设计需要考虑响应式布局、触控友好的交互元素以及快速加载速度。Bootstrap、Materialize CSS等框架提供了预设的样式和组件,简化了移动优化的HTML模板开发。...

    浅谈pc和移动端的响应式的使用

    例如,使用响应式图片(`&lt;img srcset&gt;`和`&lt;picture&gt;`元素)可以根据设备的分辨率提供适当大小的图片,提高加载速度和用户体验。另外,导航栏在小屏幕设备上可能需要折叠成汉堡菜单以节省空间。 总之,响应式设计是...

    web前端面试题

    - 使用懒加载技术、压缩图片大小、使用 WebP 格式、采用 CDN 加速等方法可以显著提高图片加载速度。 **15. 你如何理解 HTML 结构的语义化?** - 语义化的 HTML 结构意味着使用合适的 HTML 标签来表达内容的含义,...

    浅谈react 同构之样式直出

    这使得首次加载页面时,用户可以看到完整样式的网页,而不是一个空白页面等待JavaScript加载。本文将探讨React同构中样式直出的实现方法。 首先,React同构的关键在于保持Component属性和生命周期的一致性。前后端...

    尚硅谷_前端_面试题

    这种方式会在文档完全加载后才开始加载样式表,可能导致页面先无样式后有样式的闪烁现象。 4. **介绍一下你对浏览器内核的理解?** - **浏览器内核**是指浏览器的核心组件,主要由两部分组成:**渲染引擎**和**...

    浅谈网页设计中元素定位 (2013年)

    浮动定位则广泛应用于图文混排、全图排版和网页布局中,例如使文字围绕图片排列或设置图片的排版等。然而,在使用浮动定位时,需要注意父容器的高度不会自动调整以适应子元素的变化,有时候需要手动设置容器的高度。...

    面试宝典之吊打面试官系列

    - 使用懒加载技术 - 图片压缩 - 采用WebP等现代格式 - 图片分批加载 - 使用CDN加速 **15. HTML语义化的重要性** - **问题**: 你如何理解HTML结构的语义化? - **答案**: HTML语义化是指使用合适的HTML标签来...

Global site tag (gtag.js) - Google Analytics