SVG滤镜
什么是 SVG 滤镜
SVG 滤镜与 css 滤镜类似,是 SVG 中用于创建复杂效果的一种机制。很多人看到 SVG 滤镜复杂的语法容易心生退意。本文力图使用最简洁明了的方式让大家尽量弄懂 SVG 滤镜的使用方式。
本文默认读者已经掌握了一定 SVG 的基本概念和用法。
SVG 滤镜的种类
SVG 滤镜包括了:
feBlend
feColorMatrix
feComponentTransfer
feComposite
feConvolveMatrix
feDiffuseLighting
feDisplacementMap
feFlood
feGaussianBlur
feImage
feMerge
feMorphology
feOffset
feSpecularLighting
feTile
feTurbulence
feDistantLight
fePointLight
feSpotLight
看着内容很多,有点类似于 CSS 滤镜中的不同功能:blur()、contrast()、drop-shadow() 。
SVG 滤镜的语法
我们需要使用 <defs> 和 <filter> 标签来定义一个 SVG 滤镜。
通常所有的 SVG 滤镜元素都需要定义在 <defs> 标记内。
现在,基本上现代浏览器,即使不使用 <defs> 包裹 <filter>,也能够定义一个 SVG 滤镜。
这个 <defs> 标记是 definitions 这个单词的缩写,可以包含很多种其它标签,包括各种滤镜。
其次,使用 <filter> 标记用来定义 SVG 滤镜。 <filter> 标签需要一个 id 属性,它是这个滤镜的标志。SVG 图形使用这个 id 来引用滤镜。
看一个简单的 DEMO:
<div class="cssFilter"></div>
<div class="svgFilter"></div>
<svg>
<defs>
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
</defs>
</svg>div {
width: 100px;
height: 100px;
background: #000;
}
.cssblur {
filter: blur(5px);
}
.svgFilter{
filter: url(#blur);
}这里,我们在 defs 的 filter 标签内,运用了 SVG 的 feGaussianBlur 滤镜,也就是模糊滤镜, 该滤镜有两个属性 in 和 stdDeviation。其中 in="SourceGraphic" 属性指明了模糊效果要应用于整个图片,stdDeviation 属性定义了模糊的程度。最后,在 CSS 中,使用了 filter: url(#blur) 去调用 html 中定义的 id 为 blur 的滤镜。
为了方便理解,也使用 CSS 滤镜 filter: blur(5px) 实现了一个类似的滤镜,方便比较,结果图如下:

嘿,可以看到,使用 SVG 的模糊滤镜,实现了一个和 CSS 模糊滤镜一样的效果。
CSS filter 的 url 模式
上文的例子中使用了 filter: url(#blur) 这种模式引入了一个 SVG 滤镜效果,url 是 CSS 滤镜属性的关键字之一,url 模式是 CSS 滤镜提供的能力之一,允许我们引入特定的 SVG 过滤器,这极大的增强 CSS 中滤镜的能力。
相当于所有通过 SVG 实现的滤镜效果,都可以快速的通过 CSS 滤镜 URL 模式一键引入。
多个滤镜搭配工作
和 CSS 滤镜一样,SVG 滤镜也是支持多个滤镜搭配混合使用的。
所以我们经常能看到一个 <filter> 标签内有大量的代码。很容易就懵了~
再来看个简单的例子:
<div></div>
<svg>
<defs>
<!-- Filter declaration -->
<filter id="MyFilter">
<!-- offsetBlur -->
<feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />
<feOffset in="blur" dx="10" dy="10" result="offsetBlur" />
<!-- merge SourceGraphic + offsetBlur -->
<feMerge>
<feMergeNode in="offsetBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
</svg>div {
width: 200px;
height: 200px;
background: url(xxx);
filter: url(#MyFilter);
}我们先来看看整个滤镜的最终结果,结果长这样:

CSS 可能一行代码就能实现的事情,SVG 居然用了这么多代码。(当然,这里 CSS 也不好实现,不是简单容器的阴影,而是 PNG 图片图形的轮廓阴影)
分解步骤
首先看这一段:
<!-- offsetBlur -->
<feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />
<feOffset in="blur" dx="10" dy="10" result="offsetBlur" />首先 <feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" /> 这一段,我们上面也讲到了,会生成一个模糊效果,这里多了一个新的属性 result='blur',这个就是 SVG 的一个特性,不同滤镜作用的效果可以通过 result 产出一个中间结果(也称为 primitives 图元),其他滤镜可以使用 in 属性导入不同滤镜产出的 result,继续操作。
紧接着,<feOffset> 滤镜还是很好理解的,使用 in 拿到了上一步的结果 result = 'blur',然后做了一个简单的位移。
这里就有一个非常重要的知识点:在不同滤镜中利用 result 和 in 属性,可以实现在前一个基本变换操作上建立另一个操作,比如我们的例子中就是添加模糊后又添加位移效果。
结合两个滤镜,产生的图形效果,其实是这样的:

实际效果中还出现了原图,所以这里我们还使用了 <feMerge> 标签,合并了多个效果。也就是上述这段代码:
<!-- merge SourceGraphic + offsetBlur -->
<feMerge>
<feMergeNode in="offsetBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>feMerge 滤镜允许同时应用滤镜效果而不是按顺序应用滤镜效果。利用 result 存储别的滤镜的输出可以实现这一点,然后在一个 <feMergeNode> 子元素中访问它。
- <feMergeNode in="offsetBlur" /> 表示了上述两个滤镜的最终输出结果 offsetBlur ,也就是阴影的部分
- <feMergeNode in="SourceGraphic" /> 中的 in="SourceGraphic" 关键词表示图形元素自身将作为 <filter> 原语的原始输入
整体再遵循后输入的层级越高的原则,最终得到上述结果。示意流程图如下:

至此,基本就掌握了 SVG 滤镜的工作原理,及多个滤镜如何搭配使用。接下来,只需要搞懂不同的滤镜能产生什么样的效果,有什么不同的属性,就能大致对 SVG 滤镜有个基本的掌握!
关于 SVG 滤镜还需要知道的
上面大致过了一下 SVG 滤镜的使用流程,过程中提到了一些属性,可能也漏掉了一些属性的讲解,本章节将补充说明一下。
滤镜标签通用属性
有一些属性是每一个滤镜标签都有,都可以进行设置的。
| 属性 | 作用 |
|---|---|
| x, y | 提供左上角的坐标来定义在哪里渲染滤镜效果。 (默认值:0) |
| width, height | 绘制滤镜容器框的高宽(默认都为 100%) |
| result | 用于定义一个滤镜效果的输出名字,以便将其用作另一个滤镜效果的输入(in) |
| in | 指定滤镜效果的输入源,可以是某个滤镜导出的 result,也可以是下面 6 个值 |
in 属性的 6 个取值
SVG filter 中的 in 属性,指定滤镜效果的输入源,可以是某个滤镜导出的 result,也可以是下面 6 个值:
| in 取值 | 作用 |
|---|---|
| SourceGraphic | 该关键词表示图形元素自身将作为 <filter> 原语的原始输入 |
| SourceAlpha | 该关键词表示图形元素自身将作为 <filter> 原语的原始输入。SourceAlpha 与 SourceGraphic 具有相同的规则除了 SourceAlpha 只使用元素的非透明部分 |
| BackgroundImage | 与 SourceGraphic 类似,但可在背景上使用。 需要显式设置 |
| BackgroundAlpha | 与 SourceAlpha 类似,但可在背景上使用。 需要显式设置 |
| FillPaint | 将其放置在无限平面上一样使用填充油漆 |
| StrokePaint | 将其放在无限平面上一样使用描边绘画 |
来自:https://github.com/chokcoco/cnblogsArticle/issues/27
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!