看到很多大型的网站,都实现了图片延迟加载,即在浏览器的可视范围内才加载图片。这样最大的一个好处就是节约带宽提高用户体验,特别是对于访问量高的大型网站就显得尤为重要,往往大部分网站的流量都是图片大于文本内容,因此网站图片资源优化可以有很大的提升空间。
在说网站图片延迟加载前,先说下网站图片上传的处理。一般网站上传图片会保存原图,如果网站有多个尺寸规格的需要显示,还要按需生成不同大小的缩略图,这样做的好处就是之后可以快速使用访问,缺点是难以管理这些缩略图,增加了存储成本,算是“以空间换时间”。另外还有一种做法是“以时间换空间”,网站图片上传只保存原图,缩略图按需根据原图动态生成,这样会增加程序处理的一些成本,但可以换取更多空间。具体采用那种方式就因网站需要综合考虑的,目前我网站上传图片采用了比较懒的做法都只保留了原图。
延迟加载方式
回到网页图片延迟加载上来。为了不修改原来网页的图片输出代码,同时也考虑到客户端可能禁止JavaScript的情况,我这里的图片延迟加载提供了2种方式,一种是直接使用img的src加载,另外一种是使用自定义属性中的路径加载。第1种方式不需要修改原来代码,只需要在图片延迟加载处引用脚本,通过JavaScript获取指定延迟加载区域的img,移除img的src属性,待到页面可视区域再加载。这样有个问题就是到JavaScript执行延迟加载时,img下载请求已经发出来,或是图片已加载完了,所以只有那些还没来得急下载完成的图片才需要延迟加载。使用另外一种方式就可以很好的避免这个问题,就是用使用自定义属性来保存延迟加载路径,原img的src属性使用一个透明或其它图片代替,待到页面可视区域再设置回原来得img路径,这样就实现了真正的按需来延迟加载,这个就要求服务器在返回html代码中img标签就必须包含延迟加载路径的自定义属性。
延迟加载定位计算
在设置指定延迟加载区域后,需要监听窗口滚动和大小缩放事件,以便判断图片是否在当前可视范围内需要加载。这个地方有几个宽高度值要计算,一个是img本身在doucment中的定位坐标,另外还有整个doucment的宽高度、滚动条宽高度、可视范围宽高度。判断图片是否在当前可视范围内的条件为:img.x + img.width >= scrollLeft && img.x <= scrollLeft + window.width && img.y + img.height >= scrollTop && img.y <= scrollTop + window.height。其中img(x, y)是通过元素offsetParent计算出来的坐标定位,scrollLeft、scrollTop是滚动的宽高度,window(width, height)是可视范围宽高度,如下图所示。
这里考虑到img本身的宽高度情况,在图片延迟加载时最好可以预设图片的宽高度,这样可以充分准确地计算定位延迟加载,如果需要获取原图片宽高度可以预加载图片。另外我这里还采用了JavaScript定时器,主要是考虑原本有些图片在可视范围内可能是隐藏不显示的,当某些脚本事件触发时又显示出来了,这个时候图片也需要延迟加载。
我目前实现的图片延迟加载还算是比较简单的,定位计算部分的采用了jQuery中一些方法,这里下载ImgLazy.js图片延迟加载脚本。脚本使用直接在需要延迟加载的地方引用调用JavaScript函数,参数可选指定延迟加载区域、自定义属性名称等。
最后,再总结下图片延迟加载的优点,在不影响用户体验的同时,还减少了服务器流量压力。其实延迟加载不仅仅用于图片,比如QQ空间的动态信息也是拉滚动条显示更多的动态信息,包括微博信息列表等,这些都有这种思想在里面,即按需取所需,最大限度的优化体验!