SVG 滤镜原来还可以这么用

阅读 1387
收藏 27
2017-04-12
原文链接:svgtrick.com

开始之前先来看张图:

可以看到图中使用到了一个特殊的模糊效果,而且这个模糊效果主要有以下几个特点:

  • 模糊效果是独立于原图片的。也就说这里的模糊效果,并不是在设计软件中事先设计好的
  • 只需要几行代码就可以增加或者是删除模糊效果
  • 可以添加任何形状的模糊效果
  • 模糊效果是用SVG实现的,浏览器对于SVG的滤镜支持非常不错

实现这样的模糊效果主要是用了SVG中的滤镜来实现的。

一些关于SVG滤镜的基本知识可以去以前的这篇文章,这里就不再讲了。

自定义形状滤镜

下面就直接来讲讲怎么来创建自定义形状的SVG滤镜。

那如何来创建自定义形状的滤镜呢?比如一个简单的矩形滤镜。

这里使用了一个在线的SVG编辑工具Method-Draw。非常适合创建一些简单的形状,当然你如果使用AI等类似的设计软件也是没关系的。

创建好形状后,点击view菜单里面的Source命令,就可以得到形状的SVG代码。

为了把这个形状应用到滤镜中去,需要把这个形状转换成base64编码,打开这个在线工具,点击Provide text选项,把SVG源代码贴进去,如下图所示:

因为需要转换的是SVG代码,所以需要选择image/svg+xml这个选项,最后点击Generate Data URI,就可以得到这个形状的base64的编码。

把得到的编码粘贴到feImage标签中,如下所示:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
          <filter id="blurlayer" width="110%" height="100%">
            <feGaussianBlur  stdDeviation="4" result="blur"/>
                <feImage id="feimage" xlink:href="data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIzMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQogPGc+DQogIDx0aXRsZT5iYWNrZ3JvdW5kPC90aXRsZT4NCiAgPHJlY3QgZmlsbD0ibm9uZSIgaWQ9ImNhbnZhc19iYWNrZ3JvdW5kIiBoZWlnaHQ9IjMwMiIgd2lkdGg9IjEwMjYiIHk9Ii0xIiB4PSItMSIvPg0KIDwvZz4NCg0KIDxnPg0KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+DQogIDxyZWN0IGlkPSJzdmdfMSIgaGVpZ2h0PSIxMzMiIHdpZHRoPSIxMDI0IiB5PSI4NC41IiB4PSIwIiBmaWxsLW9wYWNpdHk9Im51bGwiIHN0cm9rZS1vcGFjaXR5PSJudWxsIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlPSJudWxsIiBmaWxsPSIjMDAwMDAwIi8+DQogPC9nPg0KPC9zdmc+" x="0" y="0"  height="300px" result="mask" />
            ... <!--more to come here -->
          </filter>
        </defs>
</svg>

从效果图可以看出,我们需要把蒙版和滤镜全部作用于一个元素上,而SVG滤镜是可以对多个源进行操作的,这里就要使用到feComposite这个元素:

<feComposite in2="mask" in="blur" operator="in" result="comp" />

feComposite元素接受两个源,并指定两个输入的重叠方式。分别指定在in和in2属性中,他的operator属性的值来决定如何合并两个源。

常用的值有:

  • over 生成的结果就是a层叠在b上面

  • in 典型的蒙版效果

  • out 反转蒙版的效果

SVG的滤镜中各种操作各种值确实有点晦涩,下面是一些常见的值的一个简单说明:

各种滤镜原子操作就不详述了,需要的时候查看官方文档即可。下面看一下这些操作的共性。除了"in"属性,下面的其他属性是所有原子操作都可用的。

x,y,width,height这几个属性不多说了,它定义了滤镜原子起作用的区域,不妨成为"滤镜子区域"吧。这几个属性是受filter元素的作用区域限制的,默认情况下,取值分别是0,0,100%,100%。这些原子的作用区域超过filter元素的作用区域都不起作用。

result,存放该步操作的结果。指定了result以后,同一个filter元素的其他后续操作都可以用in来指定其为输入。如果省略了这个值,则只能作为紧挨着的下一步操作的隐式输入,注意如果紧挨着的下一步操作已经用 in指定了输入,则以in指定的为准。

in表示该步操作的输入。省略in属性的话,将会默认使用前一步的结果作为本步的输入,如果省略的是第一步的in,则会使用"SourceGraphic"作为值(参看下面的说明)。in属性可以引用前面result存放的值,也可以指定下面6个特殊的值:

SourceGraphic:这个值代表使用当前的图形元素作为操作的输入。 SourceAlpha:这个值代表使用当前图形元素的Alpha值作为操作的输入。 BackgroundImage:这个值代表使用当前的背景截图作为操作的输入。 BackgroundAlpha:这个值代表使用当前的背景截图的Alpha值作为操作的输入。 FillPaint:这个值使用当前图形元素的fill属性的值作为操作的输入。 StrokePaint:这个值使用当前图形元素的stroke属性的值作为操作的输入。

一般常用的就是SourceGraphicSourceAlpha这两个值。

合并完滤镜后,接下来是要把滤镜效果应用到图片上,这里要用到feMerge这个元素:

<feMerge result="merge">
      <feMergeNode in="SourceGraphic" />
      <feMergeNode in="comp" />
</feMerge>

feMerge基元包裹一个feMergeNode元素列表,每个元素都指定一个输入。这些输入按照出现的顺序叠加。在这里原始图形(SourceGraphic)在滤镜的下面。

OK,到这里滤镜基本上就编写好了,接下来就是把它应用到图片上。

在demo中,直接在SVG中引入图片,使用filter="url(#blurlayer)"的方式来引用滤镜:

<image filter="url(#blurlayer)" x="0" y="0" width="100%" height="300px"   xlink:href="https://www.sitepoint.com/themes/ecommerce/wp-content/uploads/sites/4/ecom-banner-2-1_1020x304_acf_cropped-1.jpg"/>
</svg>

最终效果如下:

demo地址

玩转滤镜

明白了基本的原理后,我们可以自定义各种形状的滤镜来实现各种各样的图形效果。

demo地址

在现在越来越注重视觉表达的互联网时代,SVG这种古老的图形格式终于找到了自己的用武之地,前景一片光明。

本文主要是从Design Tricks with SVG Filters: A Masked Blur Effect这篇文章翻译而来,有疏漏或者理解不到位的地方,还请多多指教!

评论