龙空技术网

Medium是如何进行渐进式图像加载的

新钛云服 83

前言:

当前小伙伴们对“js 图片预加载”可能比较讲究,姐妹们都想要分析一些“js 图片预加载”的相关知识。那么小编同时在网上搜集了一些对于“js 图片预加载””的相关资讯,希望姐妹们能喜欢,看官们一起来学习一下吧!

最近,我正在浏览Medium上的帖子,我发现了一个很好的图像加载效果。首先,加载一个小的模糊图像,然后转换为大图像。我发现它非常整洁,想要剖析它是如何完成的。

先来一个Demo,看下图片是怎么进行加载的:

我在Medium上对此页面执行了WebPageTest测试,你可以在其中查看它的加载方式.

如果你想亲眼看到它,在你的浏览器中打开Medium的帖子(需要梯子),禁用缓存并限制响应,这样需要更长的时间来获取图像,你可以看到效果。

究竟发生了什么:

在DIV中显示渲染的图像,Medium使用<div />,其填充底部设置为百分比,应用于图像的宽高比,因此,当图像被加载时,它们可以防止高度塌陷,因为最终都要在此位置呈现。这就是大家常说的图片占内位符。加载一个比较小的图片。他需要一个非常小的缩略图,大小可能只有原版团的20%大小甚至更小,该图片在IMG标签中直接被加载,所以网页一开始打开,便显示该图片。加载图像后,将在<canvas />中绘制图像。然后通过自定义blur()函数获取图像数据并加载。您可以在main-base.bundle JS文件中看到它,虽然有点乱码。此功能与StackBlur的模糊功能类似,但不完全相同。与此同时,请求高清大图。加载主图像后,将会显示该图像并隐藏画布。 由于应用了CSS3动画,所以整体效果看起来非常流畅。

先来整体的看一下页面布局结构

<figure>

<div>

<div/> <!-- 图片占位 防止高度塌陷-->

<img/> <!-- 缩略图-->

<canvas/> <!-- 用户绘制设置模糊效果 -->

<img/> <!--大图-->

<noscript/> <!-- fallback for no JS -->

</div>

<figure>

这有一个具体的示例代码,你可以参考下对应的内容

请注意,请求的实际图像大小取决于设备

尝试重现效果

我在CodePen上实现了相同的效果,但是使用CS3过滤器来实现模糊的效果,而不是画布。

你可以在全屏幕上看到它。我建议你打开浏览器中的网络限制并禁用缓存以便完整的看到对应的动画效果。

如下所示:(3g网络环境)

值得这样做么?

很明显,有很多事情可以通过类的方式去加载图像,几年前,以高效的方式完成动画和模糊效果几乎是不可能的,但事实是,多数时延迟才是瓶颈,而不是设备的兼容性,然而我们可以利用这些视觉效果去提升用户体验。

这样控制图片的加载逻辑有哪些优点:

懒加载 使用JS控制图片的请求路径,虽然一开始请求了所有的小缩略图,但大图只有出现在视口(VIEWPORT)时,才会被请求加载。优雅的图片占位 这些占位图非常小,大小只有2KB,结合CSS3的模糊效果,可以获得比纯色更好的用户体验,而不会浪费过多的网络资源。 量身定制的图像尺寸 Medium根据发出请求的设备提供不同的图像大小,从而优化页面的重量

使用Data-url 方式

就是base64 因为缩略图很少 没必要从外部请求,可以直接将缩略图转成base64存放的html中,但这样会增大html文件的大小,但是可以快速的渲染。原作者经过测试,效果和外部请求类同,相差不大。

模糊效果

默认情况下,浏览器将图片放大的在展示的时候会稍微用点模糊效果在图片上,这样的效果也可以取消掉。从而避免让大家觉得如此“粗犷”的完成渲染。参见Google Developers。

当然这种效果可以在Chrome,Firefox,Safari中工作(IE未测试),不过Chrome的效果会更好点。

记住这样的图片只有27像素,并且质量非常低,这样反而可以带来一种极好的效果。但是,如果上面的效果对你而言还不够完美的话,我们可以考虑更为复杂的方案。

我们可以通过使用CSS 滤镜.而且现在有很多浏览器都系支持该特性.我相信Medium的工程师在考虑用canvas之前,一定想到过这样的方式,可能是她们觉得这种方式不值得鼓励,从而放弃使用Css了。

这种方式的主要优点就是你可以通过Css去控制你需要模糊的程度,而且相对容易实现。

还有一种方式是,你可以尝试SVG的模糊效果,详见The “Blur Up” Technique for Loading Background Images和Textured Gradients in Pure CSS.

谷歌是如何使用图片预加载的

当我们搜索图片的时候,我们会看到下面这种情况:

谷歌在进行图片加载的时候会预先将背景渲染出一种固定的颜色,随后才显示完成加载的图片。

他们可能使用的是图片中最主要的色彩,然后将其运用在背景上,从而给人一种快速加载的效果。

Facebook的 200 byte方案

早些时候facebook发表过一篇 图片预览背后的技术,里面阐述了它们是如何展示一张42px x 42px 的并且去掉JPEG头的图片。

由于这些图片是用于服务端,它们知道该如何去添加一个明确的压缩头部的JPEG。但是做网站的我们,只能依靠JavaScript去完成这样的工作。我们可以尝试使用Worker 去完成组装,然后在利用JS去发出图片内容的请求。

无论如何,这都看起来像是对于Web扼杀,但我还是建议大家阅读下使用Webp去生成小的的缩略图。

LQIP(压缩图片优先呈现)

不用等到最终的图片完成渲染,我们可以提供一张高度压缩的图片先展示出来,然后在将其替换掉.这大概就是LQIP的主要内容。其实这和Medium的方式大同小异,只不过这个方案要求更高的图片压缩,但是维持和原图的一致的像素。

结论

随着我们的页面加载越来越多的图像,最好考虑下如何优化图片的加载过程,因为它会影响性能和用户体验。如果我生成了许多大小不同的缩略图,那么你可以实现下,当图片加载时,使用小的缩略图做背景。

原文链接:

原文作者: José M. Pérez

标签: #js 图片预加载