詳解feColorMatrix

EdgardoLecl 8年前發布 | 15K 次閱讀 SVG CSS 前端技術

來自: http://www.w3cplus.com/svg/finessing-fecolormatrix.html

你見過去年年底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 + 0
0 1 0 0 0 // G = 0*R + 1*G + 0*B + 0*A + 0
0 0 1 0 0 // B = 0*R + 0*G + 1*B + 0*A + 0
0 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></pre>

這就是將 green 過濾器添加到圖像上,其結果看起來像這樣:

混合通道

你也可以通過混合RGB通道得到固定的顏色,并且給圖像著色:

<!-- lacking the B channel (mix of R & G)
Red + Green = Yellow
This 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></pre>

上面的示例,是在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></pre>

在接下來的示例中,紅色的矩陣基礎上給 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></pre>

把 -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></pre>

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 NaborsDev 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 : 允許創建紋理

擴展閱讀

本文根據 @Una Kravets 的《 Finessing feColorMatrix 》所譯,整個譯文帶有我們自己的理解與思想,如果譯得不好或有不對之處還請同行朋友指點。如需轉載此譯文,需注明英文出處: http://alistapart.com/article/finessing-fecolormatrix

大漠

常用昵稱“大漠”,W3CPlus創始人,目前就職于手淘。中國Drupal社區核心成員之一。對HTML5、CSS3和Sass等前端腳本語言有非常深入的認識和豐富的實踐經驗,尤其專注對CSS3的研究,是國內最早研究和使用CSS3技術的一批人。CSS3、Sass和Drupal中國布道者。2014年出版《 圖解CSS3:核心技術與案例實戰 》。

</div> </div>

 本文由用戶 EdgardoLecl 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!