博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用高斯模糊的效果逐步加载图片(仿 Medium)
阅读量:6246 次
发布时间:2019-06-22

本文共 2538 字,大约阅读时间需要 8 分钟。

用过 Medium 的用户不会不记得它的图片加载方式——纯色-高斯模糊-加载完成并显示

这是一种很优雅的图片预加载的方式(因为 Medium 的图片质量都很高,如果全部一下加载的话,需要的时间难以想象,所以,这是一种很棒的做法)。从第一次打开 Medium 这个网站开始,我就被这种技术给吸引住了——好吧,直到今天才去研究它。

在 Medium 网站,打开任何一篇文章,然后,我们来 inspect 一下:

可以看到,Medium 为每一张图片都设置了这么长的一段 HTML。这样做的目的就是为了让这个图片的逐步加载过程能够平滑如一,同时还能在一定程度上提升用户体验。就算图片没有加载出来,显示给用户的是一个高斯模糊的图片,其实也不失美感。

那么,这个图片的逐步加载过程具体是什么样的呢?

  1. 渲染一个 div 容器,这个容器就是用来显示最终展示给用户的图片的。通过对容器设置一个百分比的 padding-bottom 来让其比例和大小与最终图片的比例和大小相同,这样,就能避免图片加载出来的时候导致的页面的重排;

  2. 使用 img 标签来加载一张原图质量的 10% ~ 20% 左右的图片,这张图片的质量很低,而且很小,所以可以马上加载出来;

  3. 一旦小图加载完成,就开始使用 canvas 来进行绘制,添加模糊效果,同时,开始请求最终要加载的大图;

  4. 当最终的大图也加载完成之后,显示大图,隐藏掉 canvas。

以上就是 Medium 的做法。


我们可以自己来实现这个效果,实现过程如下:

  1. 渲染一个容器,保持与原图的比例和尺寸相同,填充一个较浅的背景色;

  2. 先加载小图,同时使用模糊效果;

  3. 小图加载完成,开始请求大图;

  4. 大图加载完成,显示大图,隐藏小图。

所以,综合来看,其实并不复杂。

首先,我们可以把大图和小图的 URL 和尺寸都存起来,通过标签的 data 属性去动态获取。所以,我们的 HTML 可以像下面这样写:

其中各个参数代表的含义是:

  • data-real-width: 大图的宽度

  • data-real-height: 大图的高度

  • data-src: 小图的 URL

  • src: 大图的 URL

同时,我们需要定义一些 CSS 的 class 来对大图和小图进行处理:

.blur-img-container {    position: relative;    background: #eeeeee;    background-size: cover;    overflow: hidden;}.blur-img-container img {    position: absolute;    top: 0;    left: 0;    width: 100%;    height: 100%;    opacity: 0;    transition: all 0.4s ease-in-out;}.blur-img-container .thumb-loaded {    opacity: 1;    filter: blur(10px);    transform: scale(1);}.blur-img-container .large-loaded {    opacity: 1;}.blur-img-container .thumb-hidden {    opacity: 0;}

然后,我们的重点在于 JavaScript 的处理。

  • 需要动态的设置每个图片的容器的 padding-bottom 以防止页面发生重排;

  • 通过 imageonload 事件来控制其样式和进度

第一点,动态设置我们的容器的 padding-bottom。可以通过计算宽高比然后换算成百分比:

elem.style.paddingBottom = `${(realHeight / realWidth) * 100}%`;

第二点,使用图像的 onload 事件来控制加载的进度:

let thumb = new Image();thumb.src = thumbSrc;thumb.onload = () => {    // 小图加载完成,显示小图,设置样式    setStyle(thumb, 'thumb-loaded');};elem.appendChild(thumb);let realImg = new Image();realImg.src = lgSrc;realImg.onload = () => {    // 大图加载完成,显示大图,隐藏小图    setStyle(realImg, 'large-loaded');    setStyle(thumb, 'thumb-hidden');};// 将大图添加到页面中elem.appendChild(realImg);

其实,只要把上面两点主要的功能做好了,我们的这个效果基本上就实现了。


可以通过我的 GitHub Repo 来查看完整的源代码和例子

同时,我将这个小功能封装成了一个 package,需要的朋友可以通过 npm install blur-image 或者 bower install blur-image 进行安装和使用。具体的安装和使用方法可以查看文档

参考链接

转载地址:http://fvlia.baihongyu.com/

你可能感兴趣的文章
本分类说明 -- django
查看>>
Android Binder IPC分析
查看>>
mysql分隔字符串,并将分隔字符串作为新列
查看>>
图学java基础篇之集合
查看>>
Tomcat源码分析------ 架构
查看>>
如何分析并策划好网站
查看>>
解决Skype一台电脑登陆多个账号的问题
查看>>
Gradle构建卡住问题解决
查看>>
linux使用cron任务定时执行数据库操作
查看>>
实验11 原始套接字
查看>>
C#配置Properties.Setting
查看>>
Tomcat:为Filter过滤器设置参数
查看>>
在线编辑、展示HTML、CSS、Javascript的网站
查看>>
java读取csv文件
查看>>
js判断是否为360浏览器
查看>>
京华科讯存储虚拟化技术
查看>>
Python模板库Mako的用法
查看>>
Spring整合shiro,使用jdbcTmplate操作SessionDAO
查看>>
Hibernate所鼓励的7大措施
查看>>
Python对进程Multiprocessing基础
查看>>