·设为首页
·收藏本站
·网站地图
当前位置:精诚首页 > 新技术 > 网页设计 >
网页设计

实现网页图片预加载效果的3种技术方法2015年7月

时间:2015-07-28 15:52 编辑:精诚网络 点击:

网站开发时经常需要在某个页面需要实现对大量图片的浏览,如果考虑流量的话,大可每个页面只显示一张图片,让用户每看一张图片就需要重新下载一下整个页面。不过,在web2.0时代,更多人愿意用javascript来实现一个图片浏览器,让用户无需等待过长的时间就能看到其他图片。所以,对于一个网站来说,网页的预加载就显得尤为重要。在此,马海祥从网上找了3种预加载的代码,就在马海祥博客上跟大家分享一下,共同分析一下:

一、常规实现图片预加载的方法

知道了一张图片的地址,需要把它在一个固定大小的html容器(可以是div等)里边显示出来,最重要的当然是需要知道这张即将显示的图片的宽和高,然后再结合容器的宽和高,按照一定的缩放比例使图片显示出来。因此,实现图片预加载就成为图片浏览器的核心功能了。

做过图片翻转效果的朋友其实都知道,要让图片轮换的时候不出现等待,最好是先让图片下载到本地,让浏览器缓存起来。这时,一般都会用到js里边的Image对象。一般的手段无非这样:

通过调用preLoadImg函数,传入图片的url,就能使图片预先下载下来了。实际上,马海祥觉得这里用到的预下载功能也和这基本一致。图片预下载下来后,通过img的width和height属性,就能知道图片的宽和高了。

但是需要考虑到,在做图片浏览器功能时,图片都是实时显示的。比如你点了显示的按钮,这个时候才会调用上边类似的代码来加载图片。因此,如果你直接用img.width的时候,图片还没有完全下载下来。因此,需要用一些异步的方法,等到图片下载完毕的时候才会再对img的width和height进行调用。

实现这样的异步方法实际上不难,图片的下载完毕事件也很简单,就是简单的onload事件。因此,我们可以利用下面的代码:

在firefox中测试一下,发现不错,果然和预想的效果一样,在图片下载后,就会弹出图片的宽度来。无论点击多少次或者刷新结果都一样。

不过,做到这一步,先别高兴太早——还需要考虑一下浏览器的兼容性,于是,赶紧到ie里边测试一下。实现网页图片预加载效果的3种技术方法2015年7月28日网页设计没错,同样弹出了图片的宽度。但是,再点击load的时候,情况就不一样了,什么反应都没有了。刷新一下,也同样如此。

经过对多个浏览器版本的测试,发现ie6、opera都会这样,而firefox和safari则表现正常。其实,原因也挺简单的,就是因为浏览器的缓存了。当图片加载过一次以后,如果再有对该图片的请求时,由于浏览器已经缓存住这张图片了,不会再发起一次新的请求,而是直接从缓存中加载过来。

对于firefox和safari,它们视图使这两种加载方式对用户透明,同样会引起图片的onload事件,而ie和opera则忽略了这种同一性,不会引起图片的onload事件,因此上边的代码在它们里边不能得以实现效果。

怎么办呢?最好的情况是Image可以有一个状态值表明它是否已经载入成功了。从缓存加载的时候,因为不需要等待,这个状态值就直接是表明已经下载了,而从http请求加载时,因为需要等待下载,这个值显示为未完成。这样的话,就可以搞定了。

经过一些分析,马海祥终于发现一个为各个浏览器所兼容的Image的属性——complete。所以,在图片onload事件之前先对这个值做一下判断即可。最后,代码变成如下的样子:

经过这么一番折腾,总算是让各个浏览器都能满足我们的目标了。虽然代码很简单,但是却把图片浏览器中最核心的问题解决掉了,接下来你所要做的,仅仅是图片如何呈现的问题了,当然,也可以通过css来实现图片的展示效果,谷歌网站推广具体可查看马海祥博客的《CSS无图片技术的实现方法有哪些》,在此,我就不多说了。

二、动态图片的预加载技术

一般来说,技术人员在实现图片预加载的大体思路都是这样的:

马海祥觉得这个方法功能是ok的,但是有一些隐患,具体如下:

1、创建了一个临时匿名函数来作为图片的onload事件处理函数,形成了闭包。

相信大家都看到过ie下的内存泄漏模式的文章,其中有一个模式就是循环引用,而闭包就有保存外部运行环境的能力(依赖于作用域链的实现),所以img.onload这个函数内部又保存了对img的引用,这样就形成了循环引用,导致内存泄漏。(这种模式的内存泄漏只存在低版本的ie6中,打过补丁的ie6以及高版本的ie都解决了循环引用导致的内存泄漏问题)。

2、只考虑了静态图片的加载,忽略了gif等动态图片,这些动态图片可能会多次触发onload。

要解决上面两个问题很简单,其实很简单,代码如下:

这样既能解决内存泄漏的问题,又能避免动态图片的事件多次触发问题。

在一些相关博文中,也有人注意到了要把img.onload设置为null,只不过时机不对,大部分文章都是在callback运行以后,才将img.onload设置为null,这样虽然能解决循环引用的问题,但是对于动态图片来说,如果callback运行比较耗时的话,还是有多次触发的隐患的。

隐患经过上面的修改后,就消除了,但是这个代码还有优化的余地:

关于这段代码,马海祥觉得其原因如下:

经过对多个浏览器版本的测试,发现ie、opera下,当图片加载过一次以后,如果再有对该图片的请求时,由于浏览器已经缓存住这张图片了,不会再发起一次新的请求,而是直接从缓存中加载过来。对于firefox和safari,它们试图使这两种加载方式对用户透明,同样会引起图片的onload事件,而ie和opera则忽略了这种同一性,不会引起图片的onload事件,因此上边的代码在它们里边不能得以实现效果。

确实,在ie,opera下,对于缓存图片的初始状态,与firefox和safari,chrome下是不一样的(有兴趣的话,可以在不同浏览器下,测试一下在给img的src赋值缓存图片的url之前,img的状态),但是对onload事件的触发,却是一致的,不管是什么浏览器。产生这个问题的根本原因在于,img的src赋值与onload事件的绑定,顺序不对(在ie和opera下,先赋值src,再赋值onload,因为是缓存图片,就错过了onload事件的触发)。应该先绑定onload事件,然后再给src赋值,代码如下:

这样内存泄漏,动态图片的加载问题都得到了解决(关于图片的优化分类可查看马海祥博客的《网站图片优化的分类有哪些》相关介绍),而且也以统一的方式,实现了callback的调用。

三、比onload更快获取图片尺寸的预加载技术

大部分技术人员使用预加载获取图片大小的方法,基本都是通过如下的代码实现的:

从以上代码,我们可以看到上面必须等待图片加载完毕才能获取尺寸,其速度马海祥还真不敢恭维,对此,我们需要改进。

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

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

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

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

马海祥博客点评:

预加载图片是一个很好提升用户体验的小激情,以及让自己的网站看起来更专业的一个途径,进度条可以让用户知道加载的进展,避免用户的冷落感,这也能显著提升你的网站形象。

本文为马海祥博客原创文章,如想转载,请注明原文网址摘自于,注明出处;否则,禁止转载;谢谢配合!

顶一下
(0)
0%
踩一下
(0)
0%
------分隔线---------------------------
声明:精诚网络网站内容中凡注明“来源:XXX(非精诚网络)”的作品,均转载自其它媒体,转载目的在于传递更多信息,其中涉及的网站优化,百度关键词优化,谷歌优化等技术细节并不代表精诚网络赞同支持其观点,并不对其真实性负责。对于署名“精诚网络”的作品系本站版权所有,欢迎站长朋友在转载同时署名来源。