SVG滤镜

摘要:SVG 滤镜与 CSS 滤镜类似,是 SVG 中用于创建复杂效果的一种机制。很多人看到 SVG 滤镜复杂的语法容易心生退意。本文力图使用最简洁明了的方式让大家尽量弄懂 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将其放在无限平面上一样使用描边绘画
后 4 个基本用不上~
来自:https://github.com/chokcoco/cnblogsArticle/issues/27


本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://shenqiku.cn/article/FLY_11339