HTML元素上的SVG滤镜

发布于 Gloria

上周看到有一篇关于CSS滤镜效果函数的文章,其中的效果函数相对来说比较容易理解,而且上手难度低。但是,这种方式仅仅是添加CSS滤镜效果众多方式中最弱的一种。今天让我们来看一看滤镜基元,这是为图片和元素添加滤镜效果另外一种更加强大的方法。

相较于效果函数,滤镜基元为我们提供了更多的东西。一方面原因是滤镜基元有更多的效果。另一方面是在两者相似的地方,滤镜基元为我们提供了更多的使用方式。

滤镜基元其实比较复杂,很难在一篇文章中展现它的全貌,在这里需要说一声抱歉。

我发现官方文档的描述比较模糊,而且缺乏一些帮助我们理解的例子。我也查过一些资料,但是大多数都是在讨论SVG滤镜本身。不过,高兴的是,我可以轻松地让例子跑起来了,这个例子会在下面给出。有一点不太满意的地方是,它不是在所有的浏览器中都能运行。但是我相信,未来这些浏览器都会支持。

什么是CSS滤镜基元?

滤镜基元和效果函数并没有多么不同。在许多方面,他们只是用不同方式做着同样的事情。基元最初是被作为SVG滤镜开发的,之后被扩展到不仅仅支持SVG图片。

像效果函数一样,滤镜基元是一种不需要图片编辑器就可以添加滤镜效果的一种方法。这使得它更加灵活,并且不具破坏性。它被写在SVG标记中,然后可以通过CSS filter属性的url值应用到图片或者元素上。

.filtered {
    filter: url(path-to-filter-primitives);
}

滤镜基元的概念不再像以前那样复杂。它只是与效果函数的书写方式不一样,它还提供了更多的选项,然后以不同的方式将滤镜应用于目标元素。例子或许是帮你弄清它是什么及其工作方式的最佳方法。

如果您从未接触过CSS滤镜相关的内容,建议您可以点击这里进行了解。

使用SVG滤镜基元

hue-rotate是一个效果函数,你可以像下面这样使用它:

filter: hue-rotate(60deg);

等价的滤镜基元会是下面这样:

<feColorMatrix type="hueRotate" values="60"/>

这是一个标记,而不是CSS,它有一个新名字,你可以看到type属性有一个和效果函数的函数名相似的值,我们还需要更多的代码来让上面的基元工作,但是我想你已经知道了基元和效果函数的关联。

让我们来看一个例子。我会将滤镜应用在下面这张图片:

HTML结构很简单:

<div class="filtered">
    <img src="images/strawberry-fields.jpg" />
</div>

CSS同样很简单:

filter: url(filters.svg#filter-primitives);

我使用了filter属性的url值,并且将url指向filters.svg文件。在这个文件中,我通过id名为filter-primitives调用了具体的滤镜。

到目前为止,步骤都很简单,现在我们需要定义相应的滤镜。这里是完整的filters.svg文件

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg xmlns="http://www.w3.org/2000/svg">
<defs>
   <filter id="filter-primitives">
     <feGaussianBlur stdDeviation="3" />
     <feColorMatrix type="hueRotate" values="270"/>
     <feColorMatrix type="saturate" values="0.75"/>
     <feBlend mode="multiply"/>
   </filter>
</defs>
</svg>

这个文件首先定义了自己是用xml语言书写的SVG文档。接下来是SVG对象。滤镜定义在defs元素中。它的id就是我们刚才在CSS中引用的那个。这里我应用了4个滤镜基元。我希望各自都可以最大化发挥各自的作用。

还有一些需要注意的事情,就是同时使用了hue-rotatesaturate,每一个都是独一无二的滤镜,但是不仅仅局限于huesaturation,它还有一个luminanceToAlpha值,你也可以直接将一个矩阵赋值给它。

我知道你已经习惯使用ps或者其它图片编辑器,同样需要注意的是,这里虽然没有所有的混合滤镜,但是我们有 normalmultiplymutiplyscreendarkenlighten

应用上面的滤镜会得到下面这张图片:

应用SVG滤镜后的图片

上面的例子能完美地在Firefox运行,但是在Chrome Canary和Safari中就悲剧了。为了让上面的例子也能在这两个浏览器中正常运行,于是,我将所有的代码都写在了index.html中。

<svg>
  <image x="0" y="0" width="800" height="600" xlink:href="images/strawberry-fields.jpg" filter="url(#filter-primitives)"></image>
</svg>

<svg>
 <defs>
   <filter id="filter-primitives">
     <feGaussianBlur stdDeviation="0" />
     <feColorMatrix type="hueRotate" values="270"/>
     <feColorMatrix type="saturate" values="0.75"/>
     <feBlend mode="multiply"/>
   </filter>
 </defs>
</svg>

所有的东西都在同一个文件中,而不是通过CSS链接外部文件。滤镜没有变。图片元素由原始的HTML图片变为SVG图片。

有趣的是,这个例子在Firefox里居然是。。。。滤镜确实应用在了图片上,但是Firefox只会显示裁切过的图片,就像下面这样:

裁切后的图片

图片和div容器已经被全尺寸渲染,但是图片会被裁切成宽高为300px150px的区域。我现在还不知道这是为什么。。

如果有人知道,可以在这里分享一下。

其它例子

这里有一些我查阅资料时候碰到的其它例子。

可以从每一个的标题看出来,它们可以汇总成三方面,SVG滤镜,CSS和SVG运用相同滤镜时使用上的细微差别,和不同浏览器对不同方式的支持程度。

滤镜基元清单

有许多我没有在上面使用到的滤镜基元都和效果函数很相似,或者说相似到能够让我们很容易理解它们到底是做什么的。还有不少的更加复杂一些的滤镜基元,但是我已经没有机会再去研究他们了

混合和合并效果

  • feBlend
  • feComposite
  • feMerge

色彩效果

  • feColorMatrix
  • feComponentTransfer
  • feFlood (flood-color and flood-opacity)

光照和光源效果

  • feDiffuseLighting
  • feSpecularLighting
  • feDistantLight
  • fePointLight
  • feSpotLight

其它特殊效果

  • feConvolveMatrix
  • feDisplacementMap
  • feTurbulence
  • feGaussianBlur
  • feImage
  • feMorphology
  • feTile
  • feOffset
  • feDropShadow

自定义效果

  • feCustom

总结

在这里我向可能引起的困惑道歉。由于官方文档缺少相关的例子,对我来说确实不是那么清晰,除此之外查阅到的资料都是讨论SVG滤镜的。这和我想要的确实有很密切的联系,但是不是同一件事情。

如果我们坚持这个滤镜效果规范,那么滤镜基元就是储存在单独文件中的SVG标记,使用filter: url(),他们可以应用在所有图片或者HTML文档中的其它元素。当SVG滤镜被储存在HTML中时,它只能应用在SVG元素上。

当我努力让它们工作,而且它们确实那样做的时候,很容易看到效果是有多么的强大。希望在不久的将来,我能够清除现在的所有困惑,然后对它们有更加深刻的理解。

本文根据@Steven Bradley的《CSS Filter Primitives — SVG Filters on HTML Elements》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://vanseodesign.com/css/filter-primitives/

Gloria

在校大学生,软件工程专业,爱前端,爱篮球,爱挑战。Life is struggle , Be a cool shit . 邮箱:gloria_n@yeah.net.。

如需转载,烦请注明出处:https://www.fedev.cn/svg/filter-primitives.htmlAir Jordan 3 For Women-024