小談SVG Filter — 輕鬆搞懂濾鏡順序in與result

蘇桓晨
9 min readJan 5, 2020

SVG濾鏡很多種效果,一個濾鏡(Filter)可以套用一種效果(Filter Primitives),也可以套用很多種效果。

是這樣的,效果在濾鏡裡面吃順序,一般依照標籤出現的順序,或透過特定屬性來修改。有些效果不加特定屬性規定順序就不能套用。

特定屬性就是「in」跟「result」了(有時還有in2,將在下章提及)。

來看看最簡單的濾鏡:

<svg width="100px" height="100px" viewBox="0 0 100 100"><defs>
<filter id="filter">
<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2"/>
</filter>
</defs>
<rect height="50" width="50" x="25" y="25" filter="url(#filter)"/></svg>
一個濾鏡(<feFilter/>)標籤含一個濾鏡效果(<feTurbulence/>),不需定義順序。

這是一個正方形跟它所套用的濾鏡,濾鏡標籤裡面只有一個濾鏡效果「feTurbulence」(可以想像成雜訊效果)。濾鏡沒有順序之分,所以目前沒有in、result發揮的餘地。

如何定義濾鏡順序?

濾鏡效果可以設定「result」屬性,讓其他濾性效果去套用它。同時,濾鏡效果可以設定「in」屬性,設定濾鏡的來源。有了「result」跟「in」,濾鏡就有了順序。

舉例:

<defs>
<filter id="filter">
<feTurbulence in="SourceGraphic" result="turbulence" type="turbulence" baseFrequency="0.05" numOctaves="2"/>
<feGaussianBlur in="turbulence" result="final" stdDeviation="10"/>
</filter>
</defs>
<rect height="50" width="50" x="25" y="25" filter="url(#filter)"/>

解釋一下這個例子,第一個雜訊效果<feTurbulence/>用in來設定它的來源「SourceGraphic」(濾鏡套用的來源圖像,在這裡是矩形<rect/>),效果的result屬性被我稱為turbulence。

第二個效果高斯模糊<feGaussianBlur/>用in來設定它的來源(也就是被叫turbulence的雜訊效果),高斯模糊的結果,就是濾鏡的結果,被我稱為final。

來源圖像套用干擾之後,再套用模糊

但通常設計師不會寫出來,因為預設上,效果順序如同標籤順序,一行一行將效果加上去,先出現的效果會成為後出現效果的來源。除非設計師不想依照標籤順序,或者特定濾鏡效果標籤要兩個來源來製作。

所以在沒有例外狀況的情形下,可以直接省略:

<defs>
<filter id="filter">
<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2"/>
<feGaussianBlur stdDeviation="10"/>
</filter>
</defs>
<rect height="50" width="50" x="25" y="25" filter="url(#filter)"/>

那什麼時候會用到in, in2, result呢?

使用in, result的情境

有兩種,設計師想改變效果的預設順序,以及所用的濾鏡需要兩個圖像來源時。

設計師想改變效果的預設順序時

假設我的濾鏡放了三個效果,但我只用兩個,就能用in, result去設定。

如果依照預設順序:

<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" />
<feFlood flood-color="red"/>
<feGaussianBlur stdDeviation="10"/>
來源圖像依順序套用了雜訊feTurbulence,又被填了紅色feFlood,又被模糊feGaussianBlur之後的結果

現在我們只要雜訊與模糊,因為某些原因要將雜訊放著備而不用,可以定義雜訊的名字(用result屬性),再定義模糊的對象是雜訊(用in屬性)即可。

<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/>
<feFlood flood-color="red"/>
<feGaussianBlur in="turbulence" stdDeviation="10"/>
藉由result與in,設計師能跳過某些濾鏡,或讓濾鏡依照自己的順序套用

這樣可以幹嘛呢?有三個理由會讓你想用in與result。

  1. 像寫程式一樣,有些人會先宣告會用到的屬性,再操作這些屬性,這時候就不希望順序會影響結果。
  2. 如果順序影響結果,濾鏡又太複雜,那麼我們需要確保每個效果的來源以及去向都是清楚的,這時候就很適合定義in與result。
  3. 其實標籤順序不能完全取代濾鏡順序。怎麼說?有些濾鏡如feDisplacementMap吃一個以上的來源,這代表設計師可能要先做好兩個沒有順序意義的標籤,因為這兩個來源不管誰先誰後都會被feDisplacementMap用掉,於是標籤順序跟濾鏡順序沒了關聯,寫到最後其實容易混淆。

result與in的限制

將W3C文件寫出來的規範整理過後,可以得到下面幾點:

  1. 一個效果(Filter Primitive)沒有設定in屬性,就會吃前面的效果,如果效果是第一個,沒有前面了,就吃圖像來源(SourceGraphic)。
<feGaussianBlur stdDeviation="10"/>
假設圖像來源是黑色矩形,將模糊黑色矩形

2. 一個效果有設定in,就依照in抓其他濾鏡的result。

<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/><feFlood flood-color="red"/><feGaussianBlur in="turbulence" stdDeviation="10"/>
最後一個效果設定in是turbulence,就抓result是turbulence的效果

3. 如果有多個同名result,就抓最靠近的前面(closest preceding)的result。

<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="papaya"/><feFlood flood-color="red" result="papaya"/><feGaussianBlur in="papaya" stdDeviation="10"/>
feGaussianBlur抓papaya,最靠近的前面的papaya是紅色油漆桶,於是抓紅色油漆桶效果

依據這兩點,我們還可以知道:

4. in只能抓前面標籤的result,抓不到其後標籤的result。

<feTurbulence in="flood" type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/><feFlood flood-color="red" result="flood"/><feGaussianBlur in="turbulence" stdDeviation="10"/>
in抓不到後面的標籤,feFlood

5. 濾鏡裡都沒有符合in的result,就抓前面的效果。

<feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" result="turbulence"/><feFlood flood-color="red" result="flood"/><feGaussianBlur in="nomatch" stdDeviation="10"/>
feGaussianBlur抓不到nomatch,就抓紅色油漆桶濾鏡

6. 只要最後一個效果有設定in,出來的結果就是最後一個效果與它的來源in,而與前面的順序無關(可參考第三點結果)

以上就是SVG順序的討論,下篇將提到「in2」的應用,如果有任何錯無煩請糾正,希望能夠幫助各位設計師們。

參考來源:

https://codepen.io/umas-sunavan/pen/XWJaVKK?editors=0010

--

--