SVG 滤镜应用:制作黏黏球效果


SVG滤镜基础

可缩放矢量图形(英语:Scalable Vector Graphics,SVG)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式。SVG由W3C制定,是一个开放标准。 —— 维基百科

SVG中的滤镜是非常强大的工具,这里只介绍了一个基础的SVG滤镜效果应用。

我们可以通过CSS就可以将SVG滤镜应用到大多数的DOM元素上。

SVG滤镜在DOM中的基本定义语法:
<svg xmlns="http://www.w3.org/2000/svg"version="1.1"> 
    <defs> 
        <filterid="name-your-filter-here"> 
             ... <!-- insert filters here --> ... 
        </filter> ... 
    </defs> 
</svg>
想将SVG滤镜应用到DOM元素上,你只需要:
.selector { 
    filter:url('#name-of-your-filter-here'); 
    /* you can also load filters from external SVGs this way: */ 
    filter:url('filters.svg#name-of-your-other-filter-here'); 

你或许需要在某些浏览器上加上Vendor(厂商前缀)属性才能使滤镜正常运行。

标签内可以包含一个或者数个基本滤镜图元, 例如Blur, Color transform或 shading。完整的基本滤镜图元请参考这里:

https://www.w3.org/TR/SVG/filters.html

让我们看看几个例子:
<filter id="blur"> 
    <feGaussianBlurin="SourceGraphic"stdDeviation="3"/> 
</filter>

这个滤镜将产生3px的blur效果到对应的对象上。

在**in=”SourceGraphic”**属性中。in属性定义了一个基本滤镜图元。SourceGraphic关键字表示一个原始的输入图形对象元素。所以只需要指定特定的图形对象作为输入, 滤镜就会应用到上面, 直接了当。

<filter id="drop-shadow"> 
    <feGaussianBlur in="SourceGraphic" stdDeviation="7" result="shadow"/> 
    <feOffset in="shadow" dx="3" dy="4" result="shadow"/> 
    <feColorMatrix in="shadow" mode="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.6 0" result="shadow"/> 
    <feBlend in="SourceGraphic" in2="shadow"/> 
</filter>

我们观察一下上面这组滤镜中第一个滤镜的result属性, 和第二个滤镜的in属性,result属性可以指定滤镜应用到result对应的元素上,而不是应用到SourceGraphic。在这组滤镜中,滤镜先对指定对象进行blur,然后对blur后的对象进行变暗处理,然后对blur后的对象和变暗后的对象进行位移运动。

请注意这组滤镜中最后一个滤镜元素, <feBlend> 图元, 它可以用不同的混合模式来把两个对象合成在一起. 在这里, 它示范了如何在一个滤镜图元中输入多个对象(通过in2属性), 你也可以在任意位置多次调用SourceGraphic关键字来混合他们. 这里它输入了SourceGraphicshadow两个result来将原始的图像叠加到我们处理的阴影效果上。

现在一些基本的SVG滤镜使用方法已经都介绍了一遍了, 现在让我们来看看如何制作出黏黏球的效果!

让对象粘起来

基本原理已经在上面阐述过了, 思路是将对象Blur并且还要增加其对比度, 就像两个对象被引力互相吸引了一样。

然而,还有几个需要注意的点:
  • 混合颜色, 除了白色和黑色, 将多种色彩混合并计算出混合后的颜色是一个难点
  • 将两个对象Blur后会使这个对象上的子元素都不可用
  • 内部的元素需要背景颜色来衬托, 所以也不能用透明, 因为透明会使子元素也透明

通过SVG滤镜,我们可以做许多CSS滤镜不能做到的事情,例如仅仅增加对象Alpha(透明通道)通道的对比度, 而不改变颜色;或者用SourceGraphic关键字来让内容一直可见;或者通过处理Alpht通过来使对象的背景也透明。

下面是基本代码:
<filter id="goo"> 
    <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/> 
    <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="goo"/> 
    <feBlend in="SourceGraphic" in2="goo"/> 
</filter>
  • 首先, 我们将10px的blur应用到了SourceGraphic, 然后将输出命名为blur
  • 然后将一个Color Matrix Filter(颜色矩阵滤镜)应用到blur的输出, 以增加Alpha通道的对比度
  • 最后, 我们将原始的对象叠加至我们处理后的效果上.

关于Color Matrix Filter

如果你之前没有接触过Color Matrix Filter, 在这里你可能会有点迷茫, 你可以先想象一个有着四行四列的表格, 如下图:

*RGBA+
R10000
G01000
B00100
A00010

每一行都表示一个通道, 分别是红, 绿, 蓝, 和Alpha, 数值表示对应属性的强度.

前四列也表示同样的属性, 返回他们对应的通道值.

对于在每个单元格内的值, 都会加到他们的对应行中那个数字与列的乘积

例如, 一个0.5在R行G列, 对每个像素, 就是将红色通道当前的绿色值*0.5.

最后一列不表示任何通道, 它用于额外的偏移量. 每个通道的值都会落在0-255这个区间内.

上面说了一大串, 其实用起来很简单. 在我们这个例子中, 我们仅仅增加了Alpha通道的对比度, 所以我们的矩阵是这样样子:
*RGBA+
R10000
G01000
B00100
A00018-7

这个矩阵没有对RGB通道进行操作, 而将Alpha通道乘了18, 然后7*255偏移量, 有效地单独增加了透明通道的对比度.

这个滤镜输入到feColorMatrix滤镜中, 我们只需要将他转换为数字序列, 像这样:

 values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7"
© Caldis