以下是 Lucas Bebber 的文章。 Lucas 是我在网络上见过的最具创意效果的创造者之一。 如此之多,以至于我无法抗拒 自己写一篇关于它们的博客文章 好几次。 这次好多了:我们请来了这位大师来解释 SVG 过滤器的运作原理以及如何使用它们来创建一个非常酷的粘性效果。
不久前,Chris 写了关于 CSS 中的形状粘合。 这个效果很酷,背后的技术也很巧妙,但是这种方法(通过普通的 CSS 过滤器)有几个缺点:没有透明度,粘合内部没有内容,很难做出除黑白以外的颜色,等等。
然而,这些天,我在玩弄 SVG 过滤器时,我发现可以使用它们来解决纯 CSS 方法的大多数问题。 在这里,您可以看到我制作的一个粘性菜单来演示这种效果。
查看 Pen CSS 粘性菜单(版本 1) by Lucas Bebber (@lbebber) on CodePen.
SVG 过滤器 101
SVG 过滤器非常强大。 这是一个相当广泛的主题。 在这里,我们只介绍理解此效果的工作原理所需的要素。
尽管有这个名字,我们仍然可以通过 CSS 将 SVG 过滤器应用于普通 DOM 元素,在大多数浏览器中。
这是定义过滤器的基本语法
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="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');
}
您可能需要供应商前缀才能使用 filter
属性。
一个 <filter>
元素包含一个或多个过滤器原语,它们是过滤器执行的操作,例如模糊、颜色变换、阴影。 可以在 这里 找到过滤器原语的完整列表。
让我们看几个例子
查看 Pen svg 模糊演示 by Lucas Bebber (@lbebber) on CodePen.
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>
此过滤器将对对象进行简单的 3 像素模糊。 注意 in="SourceGraphic"
属性。 in
属性定义了过滤器原语的输入。 SourceGraphic
是一个关键字,它返回元素的原始预过滤器图形。 因此,这意味着模糊过滤器的输入将是对象原始图形。 很简单。
现在,让我们看一个常见但更复杂的效果:投影过滤器。 这将有助于演示如何将过滤器原语链接在一起。
查看 Pen svg 投影演示 by Lucas Bebber (@lbebber) on CodePen.
<filter id="drop-shadow">
<feGaussianBlur in="SourceGraphic" stdDeviation="7" result="shadow" />
<feOffset in="shadow" dx="3" dy="4" result="shadow" />
<feColorMatrix in="shadow" type="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
属性,您可以命名过滤器的结果,然后将过滤器应用于该结果而不是源图形。 这使您能够,例如,模糊一个对象,使模糊的对象变暗,然后移动模糊和变暗的对象的位置。
注意最后一个元素,<feBlend>
原语。 它表明一些过滤器原语接受多个输入(in2
参数),并且您可以在过滤器的任何位置多次调用 SourceGraphic
关键字。 例如,最后一个过滤器采用 SourceGraphic
关键字和 shadow
结果将原始图像放回我们制作的阴影之上。
现在已经介绍了 SVG 过滤器的基本知识,让我们看看如何制作粘性效果。
使物体粘在一起
基本技术已经在 这里 介绍过。 概括地说,这个想法是将两个或多个对象模糊在一起,然后增加对比度。 很简单,而且效果很好。
查看 Pen metaballs 演示 by Lucas Bebber (@lbebber) on CodePen.
但是,正如我们之前所见,这也会
- 弄乱颜色,使其难以做出除黑白以外的颜色。
- 将内容模糊在一起,使其无法使用。
- 容器需要背景,因此没有透明度。
总而言之,这使得这种效果通常不切实际。
然而,借助 SVG 过滤器,我们可以做一些使用 CSS 过滤器无法做到的事情:我们可以只增加 alpha 通道的对比度,而不改变颜色;并且我们可以使用之前见过的 SourceGraphic
关键字,使内容也可见。 此外,由于我们正在处理 alpha 通道,它不仅是透明的,而且透明背景是*必需的*,因此请小心。
因此,这是基本代码
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" type="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>
它很短,让我们分解一下
- 首先,我们将
SourceGraphic
模糊 10 像素,并为该结果命名。 - 然后,对之前的结果,我们应用了一个颜色矩阵过滤器以增加 alpha 通道的对比度。
- 最后,我们将原始图形插入到我们制作的效果之上。
关于颜色矩阵
如果您之前没有使用过颜色矩阵过滤器,可能需要一些解释。 可以将其视为一个四行五列的表格。 它看起来像这样
| R | G | B | A | +
---|-------------------
R | 1 | 0 | 0 | 0 | 0
---|-------------------
G | 0 | 1 | 0 | 0 | 0
---|-------------------
B | 0 | 0 | 1 | 0 | 0
---|-------------------
A | 0 | 0 | 0 | 1 | 0
---|-------------------
每行代表一个通道(红色、绿色、蓝色和 alpha),用于设置通道的值。 前四列中的每一列都代表一个通道,它们返回其各自通道的当前值。 然后,单元格中的数字会向其行通道添加该数字乘以其列表示的通道的当前值的乘积的结果。 例如,R 行、G 列上的 0.5 会为每个像素的红色通道添加绿色*0.5 的当前值。 最后一列不代表任何通道,用于加减,这意味着那里的数字会向其通道添加其值乘以 255 的结果。
这是一个冗长的解释,但使用过滤器非常简单。 在我们的例子中,由于我们只增加了 alpha 通道的对比度,因此我们的矩阵将如下所示
| R | G | B | A | +
---|-------------------
R | 1 | 0 | 0 | 0 | 0
---|-------------------
G | 0 | 1 | 0 | 0 | 0
---|-------------------
B | 0 | 0 | 1 | 0 | 0
---|-------------------
A | 0 | 0 | 0 |18 |-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"
演示
有了这些,我们就可以创建基本效果了! 这里就是它
查看 Pen svg 粘性效果演示 by Lucas Bebber (@lbebber) on CodePen.
然后,您可以根据需要对其进行自定义,例如添加投影、为每个元素使用不同的颜色,或者任何您想要的东西!
注意事项
- 过滤器应该应用于元素的*容器*,而不是元素本身。
- 容器应该有一些出血区域,即它应该比其内容大一点,否则您可能会在边缘看到伪影。
边缘的伪影 -
为了能够将此过滤器应用于矩形等尖锐物体,我们必须采用更复杂的方法。 而不是将原始图像直接绘制到粘性效果之上,我们可以使用带有
atop
运算符的feComposite
过滤器来遮蔽粘性外部的任何内容。<filter id="fancy-goo"> <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" /> <feColorMatrix in="blur" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9" result="goo" /> <feComposite in="SourceGraphic" in2="goo" operator="atop"/> </filter>
查看 Pen 应用粘性过滤器的两种方法的比较 by Lucas Bebber (@lbebber) on CodePen.
这样,我们就可以使用此过滤器不仅可以制作这种花哨的粘性效果,还可以用于更简单的应用,例如,使采用多个矩形的形状的角变圆。
- 虽然此过滤器体积小,但如果应用于大区域,可能会占用大量资源,因此请注意这一点。
支持
SVG 滤镜具有良好的支持,但并非所有浏览器都支持将其应用于常规 DOM 元素,特别是 Safari。但是,它们至少在 Firefox 和 Chrome 上运行,即使是 Android 版本,如果滤镜不起作用,也会很好地降级。如果您绝对需要效果起作用,请考虑使用 SVG 元素而不是 DOM 元素。
太棒了!我们终于看到了一些真正与众不同,而不是仅仅用新名字包装老东西的东西。(比如“扁平化设计”、“幽灵按钮”等等,你懂的)。
最后一个例子看起来非常像衍射的模拟。SCCS 模拟 Arago 光斑是否太难了?
这些东西让我不理智地兴奋。期待着更多粘糊糊的 GUI!
我的天啊 :) 太棒了!我尤其喜欢圆形那个。这篇文章很棒!谢谢 Lucas!
如果它没有让我手机颤抖成一堆废铁,我会对它更兴奋;而我的手机并不差劲。
我得看看我能不能从这些东西中引出一些
will-change
行为。很酷的动画!
最后一段似乎暗示演示在 Safari 上不起作用,但它确实起作用,至少在 iOS 上是。 (但是,对于“快速点击”,会出现 300 毫秒的点击延迟)。
在 Android 上,Chrome 的性能(在 Nexus 7 2013 上)很好,但在 Firefox 上,存在严重的卡顿,几乎完全破坏了动画。
我的 Chrome 40(Ubuntu)上出了点问题。看看这里:http://gfycat.com/PerkyTidyAsiaticwildass
最后 2 个例子受到了影响,以及“Gooey Menu”的第 2 版。
我在这个教程中学到了很多。非常感谢你发布了如此详细的文章和令人惊叹的效果。
但是
filter
似乎不会搞乱 co- 哦,是的,它确实会。看起来,主色/次色是最安全的赌注,但话说回来,SVG 滤镜应该得到更广泛的支持,所以感谢你发布这篇文章。
第一个例子太棒了 ;) 谢谢 :)
我 <3 GOOOOOOOOO!
这太令人兴奋了。
就像 Gizmo 说,“有趣!酷!”
太酷了!… 当我们在 10 年前的 Flash 中这样做的时候。但是嘿,你的东西也很好 :)
说真的,干得好。
多么超级酷的动画效果!它们看起来像水滴。
当它们靠得更近时,互相吸引。
做得好!
太酷了,我真的很需要深入研究 SVG,它里面发生了一些非常酷的事情。
点击菜单的感觉真的很享受… *点击*
真的很棒的文章,很棒的文章!
我需要更多地了解 SVG,因为这太棒了!
哇,太棒了!
http://codepen.io/duncan_ie/full/MYQJoy/
这里有全彩的。
嗨,各位,你们知道如何在 iOS 上创建这种粘糊糊的效果吗?如果您能给我发邮件,我将不胜感激。非常感谢:)