延时加载图片

2015-09-14 12:05:10 +08:00
 sneezry
## 为什么要延时加载图片

正常情况下,网页中的图片是随着 DOM 流加载的,这样有两个问题:

1 、图片没有下载完成就显示出来,造成显示时图片不完整,用户网络环境恶劣时体验糟糕。

2 、一个页面存在多个图片时,浏览器是并行下载的,并不能保证在页面前面的图片就先显示出来,所以更应该让页面前面的图片先加载,尽快给用户展示一个完整的页面,而页面后面的图片就可以慢慢加载。

3 、当用户硬性刷新页面时,延时加载图片可以做到依然读取缓存,这样可以减少不必要的 CDN 流量。

项目地址: https://github.com/Sneezry/image-delay.js

Live Demo : http://sneezry.github.io/image-delay.js/example/

查看 Demo 时打开 Chrome 控制台,在 Networking 中将网络环境模拟成比较糟糕的情况(比如 Good 3G )可以更加清晰地看到加载过程,同时尝试硬性加载,可以看到后面几幅图片都是从缓存中读取的。

MIT License.
3327 次点击
所在节点    分享创造
20 条回复
pein
2015-09-14 12:17:54 +08:00
图片延时加载和图片预加载( new Image ())哪个比较好?使用效果上来说貌似是差不多的。
sneezry
2015-09-14 12:33:26 +08:00
@pein 原理是一样的,重点是加载开始的时间点,预加载如果不做特殊处理也是和 DOM 里的图一起抢资源
X-Force
2015-09-14 12:36:36 +08:00
这个可以和 srcset 兼得么?
sneezry
2015-09-14 12:43:50 +08:00
@X-Force 目前只做了 CSS 中的 -webkit-image-set 兼容, srcset 我会加进去的,不过得先研究下优先级
sneezry
2015-09-14 12:51:58 +08:00
@X-Force 啊,我理解错了,支持起来似乎并不麻烦,现在应该已经支持了,用 data-delay-setsrc 就可以了
pein
2015-09-14 14:35:06 +08:00
看了下 js 文件,有几个问题想问一下
1 , background 图片可通过增加 data-image-delay-wait 来实现图片“加载完成后显示”,但似乎没有看到检测图片是否加载完毕的代码,只有 onload 事件,没有 complete?
2 , background 图片可通过增加 data-image-delay-wait 来实现图片“加载完成后显示”,但<img>似乎只有延迟(顺序)加载而没有“完成后显示”功能?
3 ,文件最底下为什么有两个 setTimeout ?
上述的问题可能会导致,如果图片很大的话,应该还是会出现图片显示一半的情况(没实际测过,猜的)。
sneezry
2015-09-14 15:11:05 +08:00
@pein 感谢反馈 :-D

1 , onload 是个通用的做法, complete 需要轮询(如果有错误请指出)

2 , img 标签没有提供 data-image-delay-wait 方法,后续我会扩充 :-D

3 ,第一个 setTimeout 是为了达到强刷延时加载图片依然走缓存的目的,第二个是防止 window.onload 不触发导致图片不加载的问题,第二个延时时间可以通过 html 标签的 data-delay-timeout 属性设置

图片过大确实会出现显示一半的情况, live demo 里就出现了,哈哈
imxz
2015-09-14 15:12:15 +08:00
有个 lazyload 貌似实现了同样的效果
flyz
2015-09-14 15:15:59 +08:00
总觉得花瓣的效果最赞。
sneezry
2015-09-14 15:25:24 +08:00
@imxz lazyload 是一个非常出色的作品,它不仅仅支持图像的惰性加载,甚至还支持框架的惰性加载。但是遗憾的是 lazyload 并没有针对图像延时加载做过多优化, lazyload 更适合长页面的应用场景,另外好像也没有对背景图片做支持,希望 lazyload 和 image-delay.js 协同起来能给大家带来更大的便利 :-D
pein
2015-09-14 15:32:49 +08:00
@sneezry 嗯,看代码这个确实能做到顺序加载,但是“加载完显示”问题不解决的话,直观上来说顺序显示图片是做不到的,因为先加载的不一定就先显示,比如前面的图片大后面的小,就可能导致后加载的图片反而先显示,而且前面图片加载一半的情况也会出现。想象一下:前面的大图加载了一半,中间的一片空白还没加载,后面的小图都加载完了。。。
sneezry
2015-09-14 15:36:49 +08:00
@pein 确实是这样的,苹果的做法是把 DOM 的框架做好,这样不会出现出一张图,整体布局串一下。但是苹果没有做顺序加载,而是做了并行加载,原因是使用了延时加载的图都在页面的后半部分,很少有用户打开页面就马上往下滚动。并行加载的好处是速度快,缺点就是提到的加载完成顺序不可控。我会继续优化,增加顺序加载和加载完成后再显示的属性的 :-D
popok
2015-09-14 16:23:53 +08:00
@X-Force 异次元站长?
seyang1025
2015-09-14 17:33:39 +08:00
不都是 加载当前么,当前在哪个位置,就加载哪里
g0thic
2015-09-14 19:01:14 +08:00
不错,英语真 binag
wsph123
2015-09-14 21:19:58 +08:00
点击浏览器后退按钮时 可能会跳过 onload 事件,这时候需要通过 complete 进行判断是否已经载入成功
sneezry
2015-09-14 22:27:02 +08:00
@wsph123 感谢 :-D
crs0910
2015-09-16 08:39:59 +08:00
lz 请教个问题,类似 img 标签的 lowsrc 属性,实现如果 background 图片太大的话,先加载较小的图片,等大图下载完之后再替换应该怎么搞。写两个 class 吗?
sneezry
2015-09-16 09:43:33 +08:00
@crs0910 没用过,似乎兼容性不太好,不过我觉得不用做多余的处理,浏览器能够自己处理好
zqjilove
2015-09-16 11:20:45 +08:00
看着感觉用起来很麻烦的感觉

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/220540

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX