Home  >  Article  >  Web Front-end  >  详解feColorMatrix_html/css_WEB-ITnose

详解feColorMatrix_html/css_WEB-ITnose

WBOY
WBOYOriginal
2016-06-24 11:26:351893browse

你见过去年年底Spotify分享的一个主题吗?他们通过图像颜色处理,达到一个令人折服的视觉审美效果。

图像处理是一种非常强大的处理机制,在项目中添加一点小技巧,Web浏览器通过Web的过滤器可以动态处理图像色彩,这样将使你的项目能脱颖而出。

CSS vs. SVG

今年早些时候,推出的 CSSgram 库,使用CSS的 filter 和Blend Modes重新创建了 Instagram 过滤器。

现在使用CSS Blend Modes可以做一些修补,但是CSS的 filter 有一个极大的缺陷,其缺乏一个关键特性来对每个通道做处理。虽然CSS的 filter 很方便(其实就是源自于SVG的一种快捷方式),但无法提供控制RGBA通道。SVG(特别是 feColorMatrix )提供了更强大的力量,直接让CSS的 filter 升了一个层级,能更好的处理图像和得到更多的特殊效果。

SVG filters

在SVG的世界中,filter效果使用 fe- 前缀表示(就是“过滤效果”)。他们可以产生各种各样的色彩效果,也可以产生模糊和3D纹理。虽然 fe- 前缀一词有点松,但这篇文章后面做的总结都是有关于SVG的filter效果的方法。

目前浏览器对SVG filter的支持情况如下所示:

是的,在大多数情况之下,SVG filter都得到较好的支持,除非你还需要兼容IE9或IE9以下的浏览器。相对于CSS的filter和Blend Modes而言,SVG filter的浏览器支持度还是相对稳定的。不过也有一些奇怪的问题,并不像CSS的Blend Modes只在Chrome v46才会有 multiply 、 difference 和 exclusion 问题 。

注意:一些3D过滤效果,比如 feConvolveMatrix ,在某些浏览器中有已知的缺陷。尽管本文主要关注是 feColorMatrix ,但也无法做到。同时记住,在任何浏览器中性能将不可避免地遭到微小的影响。

filters的使用

SVG filters的使用基本上类似这样:

<svg>  <filter id="filterName">    // filter definition here can include    // multiple of the above items  </filter></svg>

在SVG中,你可以声明一个filter。在大多数情况之下,可以使用SVG的 defs 来声明你想要的filter,然后可以在CSS这样使用声明的filter:

.filter-me {  filter: url('#filterName');}

filter的 URL 是相对的,所以 filter: url('../img/filter.svg#filterName') 和 filter: url('http://una.im/filters.svg#filterName') 都是有效的。

feColorMatrix

当谈到颜色的处理, feColorMatrix 是你最好的选择。 feColorMatrix 是过滤中的一种类型,使用矩阵来影响颜色的每个通道(基于RGBA),你可以将其想象成Photoshop中通道编辑一样。

feColorMatrix 看起来像这样(原始图像RGBA的值默认为 1 )。

<filter id="linear">    <feColorMatrix      type="matrix"      values="R 0 0 0 0              0 G 0 0 0              0 0 B 0 0              0 0 0 A 0 "/>    </feColorMatrix> </filter>

矩阵计算RGBA自已每行的最终值,每个RGBA通道有自身的RGBA通道。最后一个值是一个乘数。最后RGBA的值从上向下读,像下面这个列表:

/* R G B A 1 */1 0 0 0 0 // R = 1*R + 0*G + 0*B + 0*A + 00 1 0 0 0 // G = 0*R + 1*G + 0*B + 0*A + 00 0 1 0 0 // B = 0*R + 0*G + 1*B + 0*A + 00 0 0 1 0 // A = 0*R + 0*G + 0*B + 1*A + 0

下图更形象:

RGB值

着色

你可以遗漏或混合颜色通道给图像着色,像下面这样:

<!-- lacking the B & G channels (only R at 1) --><filter id="red">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   0   0   0   0            0   0   0   0   0            0   0   0   1   0 "/></filter><!-- lacking the R & G channels (only B at 1) --><filter id="blue"> <feColorMatrix    type="matrix"    values="0   0   0   0   0            0   0   0   0   0            0   0   1   0   0            0   0   0   1   0 "/></filter><!-- lacking the R & B channels (only G at 1) --><filter id="green">  <feColorMatrix    type="matrix"    values="0   0   0   0   0            0   1   0   0   0            0   0   0   0   0            0   0   0   1   0 "/></filter>

这就是将 green 过滤器添加到图像上,其结果看起来像这样:

混合通道

你也可以通过混合RGB通道得到固定的颜色,并且给图像着色:

<!-- lacking the B channel (mix of R & G)Red + Green = YellowThis is saying there is no yellow channel--><filter id="yellow">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   1   0   0   0            0   0   0   0   0            0   0   0   1   0 "/></filter><!-- lacking the G channels (mix of R & B)Red + Blue = Magenta--><filter id="magenta">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   0   0   0   0            0   0   1   0   0            0   0   0   1   0 "/></filter><!-- lacking the R channel (mix of G & B)Green + Blue = Cyan--><filter id="cyan">  <feColorMatrix    type="matrix"    values="0   0   0   0   0            0   1   0   0   0            0   0   1   0   0            0   0   0   1   0 "/></filter>

上面的示例,是在CMYK模式下混合颜色,删除 red 通道将意味着 green 和 blue 依然存在。当 green 和 blue 混合将创建 cyan , red 和 blue 混合将创建 magenta 。

@Justin McDowell 曾经写过 一篇文章阐述HSL (hue, saturation, lightness)颜色。我们也需要记住,在SVG中亮度的值是指光度。在这里,每个通道都会保留一个亮度的级别,比如我们看到的图像,就保留了一个洋红色:

为什么在云上和亮度的地方会变成洋红色?看看下面的RGB颜色图:

当一个颜色值失踪后会使用其他两个值取而代之。比如,没有 green 颜色通道就会没有 white 、 cyan 或 yellow 。其实他们并没有消失,只不过他们的亮度值(或 alpha )尚未触及。让我们看看操作这些 alpha 值会发生什么?

ALPHA值

我们可以通过 alpha (第四列)来突出阴影和亮度。第四行受 alpha 通道影响,而第四列将影响每个通道的亮度值,如:

<!-- Acts like an opacity filter at .5 --><filter id="alpha">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   1   0   0   0            0   0   1   0   0            0   0   0   .5  0 "/></filter><!-- increases green opacity to be     on the same level as overall opacity --><filter id="hard-green">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   1   0   1   0            0   0   1   0   0            0   0   0   1   0 "/></filter><filter id="hard-yellow">  <feColorMatrix    type="matrix"    values="1   0   0   1   0            0   1   0   1   0            0   0   1   0   0            0   0   0   1   0 "/></filter>

在接下来的示例中,红色的矩阵基础上给 blue 的通道添加了 100% 的 alpha 。我们还保留 red 值,覆盖任何 red 的痕迹,会变成 blue ,而红色的亮度值中 blue 和 red 混合将成为 magenta 。

<filter id="blue-shadow-magenta-highlight">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   0   0   0   0            0   0   1   1   0            0   0   0   1   0 "/></filter>

如果最后一个值小于 0 (变成 -1 ),就会得到相反效果。 blue 的痕迹就会变成 red 。下面就是取值为 -1 的效果:

<filter id="red-overlay">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   0   0   0   0            0   0   1  -1   0            0   0   0   1   0 "/></filter><filter id="identical-red-overlay">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   0   0   0   0            0   0   0   0   0            0   0   0   1   0 "/></filter>

把 -1 换成 .5 ,混合后颜色效果如下:

<filter id="blue-magenta-2">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   0   0   0   0            0   0   1  .5   0            0   0   0   1   0 "/></filter>

Blowing out channels

我们也可以通过第四行的个人通道影响整个 alpha 通道。示例中有一个蓝色的天空,可以将蓝色的天空变成白色,如下:

<filter id="elim-blue">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   1   0   0   0            0   0   1   0   0            0   0   -2   1   0 "/></filter>

下面演示几个混合通道的示例:

<!-- No G channel, Red is at 100% on the G Channel, so the G channel looks Red (luminosity of G channel lost) --><filter id="no-g-red">  <feColorMatrix    type="matrix"    values="1   1   0   0   0            0   0   0   0   0            0   0   1   0   0            0   0   0   1   0 "/></filter><!-- No G channel, Red and Green is at 100% on the G Channel, so the G Channel looks Magenta (luminosity of G channel lost) --><filter id="no-g-magenta">  <feColorMatrix    type="matrix"    values="1   1   0   0   0            0   0   0   0   0            0   1   1   0   0            0   0   0   1   0 "/></filter><!-- G channel being shared by red and blue values. This is a colorized magenta effect (luminosity maintained) --><filter id="yes-g-colorized-magenta">  <feColorMatrix    type="matrix"    values="1   1   0   0   0            0   1   0   0   0            0   1   1   0   0            0   0   0   1   0 "/></filter>

Lighten 和 darken

您可以通过将RGB值每个通道的值设置成小于 1 创建一个 darken 效果,反之,将每个通道值设置成大于 1 可以创建一个 lighten 效果。下图能清晰的阐述这一切:

矩阵效果如下:

<filter id="darken">  <feColorMatrix    type="matrix"    values=".5   0   0   0   0             0  .5   0   0   0             0   0  .5   0   0             0   0   0   1   0 "/></filter>

<filter id="lighten">  <feColorMatrix    type="matrix"    values="1.5   0   0   0   0            0   1.5   0   0   0            0   0   1.5   0   0            0   0   0   1   0 "/></filter>

GRAYSCALE

你可以在一列中设置shade的像素值创建出灰度效果。运用的通道位置不一样,可以得到不同的灰度值。比如下面几个示例:

<filter id="gray-on-light">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            1   0   0   0   0            1   0   0   0   0            0   0   0   1   0 "/></filter>

<filter id="gray-on-mid">  <feColorMatrix    type="matrix"    values="0   1   0   0   0            0   1   0   0   0            0   1   0   0   0            0   0   0   1   0 "/></filter>

<filter id="gray-on-dark">  <feColorMatrix    type="matrix"    values="0   0   1   0   0            0   0   1   0   0            0   0   1   0   0            0   0   0   1   0 "/></filter>

组合在一起

feColorMatrix 真正力量是能够混合多个通道,并且将这些概念运用到图像上产生一个新的图像效果。

<filter id="peachy">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0  .5   0   0   0            0   0   0  .5   0            0   0   0   1   0 "/></filter>

在 red 的通道上采用 1 , green 通道上采用 0.5 ,而 blue 通道不在正常的位置上,而 alpha 设置为 0.5 。看到的效果是深蓝色的痕迹(shadows),突出的红色和一半亮度绿色的混合的中间色调。如果 red + green = blue 的话,那么 red + (green / 2) 能得到更多的 coral 色:

这是另一个示例:

<filter id="lime">  <feColorMatrix    type="matrix"    values="1   0   0   0   0            0   2   0   0   0            0   0   0  .5   0            0   0   0   1   0 "/></filter>

有这么多值得探索的值。 Rachel Nabors 的 Dev Tools Challenger 就是一个很好的示例。( 注: 需要使用Firefox浏览器打开)。

酷!科学!颜色过滤器!现在,你对这方面知识有一定的了解。你现在所需要的是需要自己的工具来创建你自己的效果。

如果你想了解更多的细节,建议你阅读 Amelia Bellamy-Royds 写的 一篇文章 ,文章阐述了 feColorMatrix 更多的细节。 Sara Soueidan 也写了 一篇文章 ,在SVG中使用CSS的blend modes模式创建图像效果。

filter效果的参考

如查你理解了 feColorMatrix 是什么,你就可以在此基础上创建一个工具来生成过滤器效果。下面提供一些 fe- 相关的选项,希望对你有所帮助,并且能做进一步的探索。

  • feBlend :类似于 CSS blend modes ,描述了图像通过混合模式进行交互
  • feComponentTransfer : 改变个人对RGBA通道的总称(如 feFuncG )
  • feComposite :一个原始的过滤器, 定义像素图像交互方式
  • feConvolveMatrix :这个过滤器规定像素与他近邻将关闭交互(如:模糊、锐化)
  • feDiffuseLighting :定义了一个光源
  • feDisplacementMap : 使用另一个输入值( in2 )取代一个图像的像素值( in )
  • feFlood : 完成过滤器的填充区域指定的颜色和 alpha 等级
  • feGaussianBlur :输入的模糊值和标准值的偏差
  • feImage :使用其他的过滤器(像 feBlend 或 feComposite )
  • feMerge : 允许异步过滤效果应用,而不是分层
  • feMorphology : 削弱或扩张源图像
  • feOffset :用来创建阴影
  • feSpecularLighting : 通过 alpha 创建凹凸贴图,又将其称之为" 镜面 "( Phong Reflection Model )
  • feTile : 指图像如何重复填补空间
  • feTurbulence : 允许创建纹理

扩展阅读

  • MDN Docs on feColorMatrix
  • w3c Filter Docs
  • Smarter SVG Filters
  • feColorMatrix Overview on Web Platform
  • SVG 研究之路 (11) - filter:feColorMatrix

本文根据 @Una Kravets 的《 Finessing feColorMatrix 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: http://alistapart.com/article/finessing-fecolormatrix 。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn