使用SVG滤镜创造Gooey效果
今天我们将演示如何使用SVG Filter在HTML元素上实现沾粘效果( gooey-like effect )。我们首先讲解基础知识,然后再演示几个针对web元素的创造性用例,比如菜单,app, selection,页面导航等。
注意 这种效果只是试验性的,只支持现代浏览器。
我们首先深入了解SVG Filter,并懂得如何应用它们。
SVG 滤镜
SVG滤镜 可以用一个或者多个操作修改指定的源图像并创造出另一种效果的版本。SVG中的每一个滤镜元都包含了一套执行某种图像操作的滤镜原语( filter primitive),可用的 滤镜原语如下:
- feBlend
- feColorMatrix
- feComponentTransfer
- feComposite
- feConvolveMatrix
- feDiffuseLighting
- feDisplacementMap
- feFlood
- feGaussianBlur
- feImage
- feMerge
- feMorphology
- feOffset
- feSpecularLighting
- feTile
- feTurbulence
- feDistantLight
- fePointLight
- feSpotLight
在使用filter的时候,我们可以使用一个操作的结果作为另一个滤镜的输入,以此实现无尽可能的效果。这也是滤镜的真正强大之处。
SVG 滤镜的一个常见例子是使用 来 实现模糊效果:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="400">
<defs>
<filter id="blur" x="0" y="0">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
</defs>
<rect x="50" y="50" width="500" height="300" fill="#8d81ac" filter="url(#blur)" />
</svg>
结果如下:
in属性定义filter primitive的输入。可以使用如下的关键词:
- SourceGraphic
- SourceAlpha
- BackgroundImage
- BackgroundAlpha
- FillPaint
- StrokePaint
我们还可以使用引用前一个result属性的string。result属性让我们可以把一个filter操作的结果作为另一个filter操作的输入(用in指定输入)。这点在我们的Gooey例子中将使用到。
一个更复杂的例子就是把多个滤镜原语结合在一起形成投影效果:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="400">
<defs>
<filter id="dropshadow" x="0" y="0" width="200%" height="200%">
<feOffset result="offsetResult" in="SourceAlpha" dx="20" dy="20" />
<feGaussianBlur result="blurResult" in="offsetResult" stdDeviation="5" />
<feBlend in="SourceGraphic" in2="blurResult" mode="normal" />
</filter>
</defs>
<rect width="500" height="300" fill="#8d81ac" filter="url(#dropshadow)" />
</svg>
结果如下:
我们首先让元素偏移,然后模糊这个偏移了的“拷贝”。使用blend源语是为了把原始元素放在模糊了的结果之上。使用in="SourceAlpha"可以使模糊是黑色的。如果我们使用的是in="SourceGraphic",那么“阴影”将是原始元素的颜色。
HTML的SVG滤镜
对HTML元素使用SVG滤镜很简单。首先,我们在HTML的某处定义滤镜,然后在样式中使用它:
.filterClass {
-webkit-filter: url("#goo");
filter: url("../index.html#goo");
}
对non-webkit属性定义了不同路径的原因是Firefox引用滤镜的方式。作为一个相对路径,如果只使用#goo,它将指向样式文件而非使用它的HTML,结果是找不到滤镜。使用内联样式(css和html在一个文件中)或者按照我们这里的方法都可以解决这个问题。我们还可以使用JavaScript来添加滤镜效果:
function setFilter(value){
$effectContainer.css({
webkitFilter: value,
filter: value,
});
}
这里value可以是类似于我们这里定义的 ‘url(#goo)’这样的值。
HTML元素上使用SVG滤镜目前的支持还是不错的。
下面是一些学习与实践SVG滤镜的不错的资源:
- Applying SVG effects to HTML content
- Hands On: SVG Filter Effects
- Cross-browser filters with CSS and SVG
- Smarter SVG filters
- How to go beyond the basics with SVG filters
使用Gooey滤镜
让我们看看其中的一个demo,了解实际是如何工作的:
这个例子的html如下:
<div class="menu">
<div class="menu-wrapper">
<ul class="menu-items">
<li class="menu-item">
<button class="menu-item-button">
<i class="menu-item-icon icon icon-reply"></i>
</button>
<div class="menu-item-bounce"></div>
</li>
<li class="menu-item">
<button class="menu-item-button">
<i class="menu-item-icon icon icon-box"></i>
</button>
<div class="menu-item-bounce"></div>
</li>
<li class="menu-item">
<button class="menu-item-button">
<i class="menu-item-icon icon icon-trash"></i>
</button>
<div class="menu-item-bounce"></div>
</li>
</ul>
<button class="menu-toggle-button">
<i class="fa fa-plus menu-toggle-icon"></i>
</button>
</div>
</div>
我们还在SVG对象里面定义了一个滤镜,这个SVG对象将被放到HTML中:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<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 19 -9" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
现在,我们使用CSS的filter属性把滤镜应用到我们想沾粘到一起的元素的容器中:
.menu {
/* other styles */
-webkit-filter: url("#goo");
filter: url("../menu.html#goo");
}
现在,让我们把滤镜拆开来分析。滤镜所作的第一个操作就是模糊,通过feGaussianBlur滤镜实现:
下一个操作是使用feColorMatrix滤镜。这里是用它来增加alpha值的对比度,把它与模糊一起使用,就会造出水滴沾粘效果:
在这里学习更多关于应用颜色矩阵的知识。
最后,为了让内容可见,我们在刚刚做出的效果之上绘制了原始图像。为此,我们使用了带atop操作的feComposite滤镜。
完工!记住这个filter非常消耗资源,因此要避免大面积使用。
例子
下面的demo将演示一些在不同控件上使用Gooey效果的例子:
我们希望你能从这些例子中得到启发。注:这些例子的动画效果是配合JS实现的。