寒假比赛总结(五) - 基于现有解决方案实现背景虚化
前言
我对目前比较成熟的背景虚化方案还不是很熟悉,但是这次比赛项目需要用到这个功能,具体体现在使用虚化的用户头像当作头像展示的背景,类似于下图:

采用这种方法的好处就是在保证大体美观的情况下减轻研发量(因为减去了用户上传背景图片的功能)。
解决方案
1.基于CSS3的高斯模糊滤镜
此方案具体实现就是类似于实现毛玻璃特效的blur()
滤镜,通过叠加背景图片达到高斯模糊效果。
此方案我最开始是在Lea Verou所著的《CSS揭秘》一书中发现的,并且作者最初也是为了实现毛玻璃特效使用了高斯模糊。之所以认为它可以用于实现这个需求,是因为其本质是背景图片模糊。
过程
- 建立一个容器,宽高指定,指定所需背景图片:
HTML
<div class="head-wrapper" :style="{background: `url(../../../static/images/${this.avatar})`}">
Less
.head-wrapper {
min-height: 161px;
height: auto;
width: 100%;
position: relative;
background-repeat: no-repeat !important;
background-size: 80% !important;
background-position: center !important;
transition: all .5s;
overflow: hidden;
user-select: none;
}
- 给该容器增加一个伪元素
::before
,背景设置为继承宿主父元素.head-wrapper
:
Less
.head-wrapper {
min-height: 161px;
height: auto;
width: 100%;
position: relative;
background-repeat: no-repeat !important;
background-size: 80% !important;
background-position: center !important;
transition: all .5s;
overflow: hidden;
user-select: none;
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: inherit;
filter: blur(4px);
margin: -20%;
z-index: 0;
}
}
background-size
之所以设置成80%,是因为CSS3的blur滤镜并不会全部覆盖整个容器,周围会有消退的问题。为了修补这个问题,需要在伪元素中再相对于宿主元素的尺寸向外扩大20%。此时,如果background-size
仍然设置成100%,会导致背景图片显示不全的问题。为了修复这个问题,我们需要将图片大小缩小20%,背景图片位置居中。
2.基于SVG的解决方案
这个方案使用起来应该没有CSS3滤镜那么多bug,但是因为我对SVG并不是特别熟悉,所以就直接贴代码,留作以后备用:
<div data-v-2ff4b7a0="" style="height: 200px; position: relative; overflow: hidden;">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="375" height="200" id="blurred_gto44jls8" class="vux-bg-blur" viewBox="0 0 375 200" preserveAspectRatio="none" style="opacity: 1;">
<filter id="blur_gto44jls8">
<feGaussianBlur in="SourceGraphic" stdDeviation="40"></feGaussianBlur>
</filter>
<image x="0" y="0" width="375" height="200" externalResourcesRequired="true" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://o3e85j0cv.qnssl.com/tulips-1083572__340.jpg" style="filter:url(#blur_gto44jls8)" preserveAspectRatio="none"></image>
</svg>
...
</div>
此代码的实现效果是文中开头的图片,反正我觉得这个比较简单,而且效果也比CSS好看。
我最终采用了方案一,效果图如下:
