SVG 濾鏡元件之二

濾鏡列表

SVG 中可用的濾鏡元件有:

照明濾鏡(Lighting Filters)

要使用 SVG 創建燈光效果,您需要指定一些內容: 照明濾鏡將採用以下結構:
<type of lighting in="" lighting-color="">
   <light source />
 </type of lighting>

<fePointLight>

<feSpotLight>

<feDistantLight>

<feSpecularLighting>

<feSpecularLighting> SVG 濾鏡基元指定從反射面反射的二次光。
 <filter id = "filter">
    <feSpecularLighting result="specOut"
        specularExponent="20" lighting-color="#bbbbbb">
      <fePointLight x="50" y="75" z="200"/>
    </feSpecularLighting>
    <feComposite in="SourceGraphic" in2="specOut"
        operator="arithmetic" k1="0" k2="1" k3="1" k4="0"/>
  </filter>
  <circle cx="110" cy="110" r="100" style="filter:url(#filter)"/>

<feDiffuseLighting>

<feDiffuseLighting> SVG 濾鏡基元來自外部光源,適合模擬太陽光或者燈光照明。

例題:此例顯示了 <feDiffuseLighting> 元件對每個可用光源的圓的效果。 每次,光線都來自左上角。

參考資料:

<feMorphology>

濾鏡<feMorphology>對圖像中產生的結果效果是增肥(dilate)或瘦身(erode)。 這是一個相當簡單的效果,只有兩個參數控制效果的類型和大小。
  <defs>
    <filter id="Erode1">
      <feMorphology operator="erode" in="SourceGraphic" radius="1" />
    </filter>
    <filter id="Dilate1">
      <feMorphology operator="dilate" in="SourceGraphic" radius="1" />
    </filter>
  </defs>
    <g font-family="Verdana" font-size="30" stroke="blue" stroke-width="1">
      <text x="50" y="40">Unfiltered</text>
      <text x="50" y="80" filter="url(#Erode1)">Erode</text>
      <text x="50" y="120" filter="url(#Dilate1)">Dilate</text>
    </g>

feMorphology 動畫 左圖是下列腳本的實現,圖像變胖或明亮(dilate)。右圖是變瘦或暗(erode)。

<svg width="450" height="300" viewBox="0 0 450 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
    <filter id="morphology">
        <feMorphology operator="dilate" radius="0">
            <animate attributeName="radius" from="0" to="5" dur="5s" repeatCount="indefinite" />
        </feMorphology>
    </filter>
    <image xlink:href="../svg/tree.jpg" width="90%" height="90%" x="10" y="10" filter="url(#morphology)"></image>
</svg>

原圖在這裡。

顯示動畫 feMorphology 效果的示例:單擊可改變

參考資料:

<feTurbulence>

<feTurbulence> 使用 Perlin 湍流(turbulence)函數創建紋理。 它創建了平滑的視覺雜訊模式,用柔和色彩漩渦填充矩形。
想像是一種雜訊,但不是粒子狀的雜訊,是RGBA都雜訊的圖像。通常會套用在 feDisplacementMap 一起用,建立皺折、雜訊、花玻璃等效果。

主要屬性有五種,baseFrequency (想像雜訊圖檔大小 0.01~1)、numOctaves (想像精 緻度 1~10)、seed (雜訊圖檔種子碼)、stitchTiles (雜訊圖檔是否拼接)、type (類型,fractalNoise較”霧面”,turbulence較顆粒)

<rect x="0" y="0" height="100%" width="100%" fill="#fff"/>
<filter id="twoF">
  <feTurbulence baseFrequency=".01" numOctaves="4" seed="200"/>
</filter>
<rect x="25%" y="25%" filter="url(#twoF)" height="50%" width="50%"/>
通過改變參數 baseFrequency、numOctaves(預設為 1.0)、type(預設為 'turbulence')、stitchTiles(預設為 'noStitch')和 seed(預設為 '0')的值, 可以產生 多種有趣的模式類型,如下圖所示:
A.
baseFrequency = ".04"
B.
baseFrequency= ".04" numOctaves="2"
C.
baseFrequency = ".04"
numOctaves="2" seed="201"
D.
baseFrequency= ".04"
numOctaves="5"
seed="201"
E.
baseFrequency = ".04"
F.
baseFrequency
= ".01"
G.
baseFrequency
= ".1" numOctaves="1"
H.
baseFrequency
= ".1" numOctaves="3"
I.
baseFrequency= ".04"
type = "fractalNoise"
J.
baseFrequency= ".01"
type = "fractalNoise"
numOctaves = "3"  
K.
baseFrequency
= ".04,.1"
L.
baseFrequency
= ".1,.01"

<feComposite>

<feComposite> 用於將兩個圖像相交。 它需需要兩個輸入,“in”和“in2”。 in 預設是 SourceGraphic。
運算符的“in”屬性用於顯示組合的結果。
<filter id="composite" y="0" x="0" width="100%" height="100%">
  <feTurbulence baseFrequency=".05" numOctaves="3" result="B"/>
  <feComposite in2="B" in="SourceGraphic" operator="in" />
</filter>
<ellipse cx="100" cy="87" rx="75" ry="87" fill="red"
      filter="url(#composite)"/>

operator 屬性用於設置如何合併這兩個輸入源:

以下示例將綠色方塊(輸入 1)和紅色方塊(輸入 2),依不同方式合併:

特殊字體

SourceGraphic 和 SourceAlpha 兩關鍵詞,都是表示圖形元件自身將作為 <filter> 基元的原始輸入。 SourceAlpha 與 SourceGraphic 具有相同的規則,除了 SourceAlpha 只使用元件的非透明部分。
<defs>
  <filter id="filter">
     <feMorphology in="SourceAlpha"
        operator="dilate" radius="2" result="OUTLINE" />
     <feComposite operator="out" in="OUTLINE"
                           in2="SourceAlpha" />
  </filter>
</defs>
<text class="filtered" x="20" y="85"
  style="filter: url(#filter);fill:black;
   font-family:'Ultra',serif;font-size:80px;">Outlined
</text>

水滴

應用 feTurbulence 和 feDiffuseLighting 造成水滴滴在紙上的效果。

源碼在這個CodePen。

參考資料:

<feTurbulence>屬性

feTurbulence濾鏡支持下面5個專有的html屬性:

<feTurbulence>應用--創造紋理

feTurbulence 可以用來創造很多紋路, 並會利用光線來達到凹凸材質的展現,相當有意思。

有紋路的紙

<defs>
  <filter id="a122401_f1" filterUnits="userSpaceOnUse">
    <feTurbulence type="fractalNoise" baseFrequency="0.03 0.06"
         numOctaves="10" result="a122401_t1" seed="1">
    </feTurbulence>
    <feSpecularLighting in="a122401_t1" lighting-color="#eed"
         specularExponent="2" surfaceScale="4" result="a122401_L1">
      <feDistantLight azimuth="45" elevation="30">
    </feSpecularLighting>
    <feComposite operator="atop" in="a122401_L1" in2="SourceGraphic">
    </feComposite>
  </filter>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="#aaa"
    style="filter: url(#a122401_f1)"></rect>

木頭紋理

<svg xmlns="http://www.w3.org/2000/svg"
            xmlns:xlink="http://www.w3.org/1999/xlink"
      width="300" height="300" style="background-color:#fff">
<defs>
  <filter id="a122408_f1" x="0" y="0" width="100%" height="100%">
    <feFlood flood-color="#722" result="a122408_fd1">
    <feFlood flood-color="#ea0" result="a122408_fd2">
    <feTurbulence type="fractalNoise" baseFrequency="0.005 0.06"
          numOctaves="1" seed="1">
    </feTurbulence>
    <feComponentTransfer color-interpolation-filters="sRGB"
             result="a122408_ft1">
        <feFuncR type="discrete" tableValues="0 0">
        <feFuncG type="discrete" tableValues="0 0">
        <feFuncB type="discrete" tableValues="0 0">
        <feFuncA type="table"
          tableValues="0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
                         0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
                         0 1 0 1 0 1 0 1 0 1 0 1">
        </feFuncA>
    </feComponentTransfer>
    <feComposite in="a122408_fd1" in2="a122408_ft1" operator="in"
          result="a122408_fcin"></feComposite>
    <feComposite in="a122408_fd2" in2="a122408_ft1" operator="out"
          result="a122408_fcout"></feComposite>
    <feComposite in="a122408_fcin" in2="a122408_fcout"
          operator="arithmetic" k1="0" k2="1" k3="1" k4="0"></feComposite>
</filter>
</defs>
<rect x="0" y="0" width="300" height="300" style="filter: url(#a122408_f1)">
</svg>

參考資料:

<feDisplacementMap>

對輸入來源1每個像素位置應用輸入來源2的顏色移置,來源1的圖片會因為來源2的顏色產生偏移。 至於哪個顏色、垂直還是左右偏,則用ChannelSelector定義。

同樣有五個屬性,in (要被影響圖像1)、in2 (要發揮影響的圖像2)、scale(幅度)、xChannelSelector (X座標要用RGBA什麼顏色)、yChannelSelector (Y座標要用RGBA什麼顏色)。

<svg width="200" height="200" viewBox="0 0 220 220"
     xmlns="http://www.w3.org/2000/svg">
  <filter id="displacementFilter">
    <feTurbulence type="turbulence" baseFrequency="0.05"
        numOctaves="2" result="turbulence"/>
    <feDisplacementMap in2="turbulence" in="SourceGraphic"
        scale="50" xChannelSelector="R" yChannelSelector="G"/>
  </filter>

  <circle cx="100" cy="100" r="100"
      style="filter: url(#displacementFilter)"/>
</svg>

應用例題: 火焰效果

<defs>
  <filter id="a122407_f1" filterUnits="userSpaceOnUse">
    <feTurbulence type="fractalNoise" baseFrequency="0.02 0.02"
            numOctaves="10" result="a122407_t1" seed="7">
    </feTurbulence>
    <feDisplacementMap in2="a122407_t1" in="SourceGraphic"
            scale="140" xChannelSelector="R" yChannelSelector="G">
    </feDisplacementMap>
  </filter>
  <radialGradient id="a122407_rad1">
    <stop offset="0%" stop-color="#ff0f">
    <stop offset="100%" stop-color="#f000">
  </radialGradient>
</defs>
  <rect x="0" y="30" width="90%" height="100%"
      fill="url(#a122407_rad1)" style="filter: url(#a122407_f1)">
  <ellipse cx="150" cy="200" rx="120" ry="200"
      fill="url(#a122407_rad1)" style="filter: url(#a122407_f1)">
  <ellipse cx="150" cy="240" rx="120" ry="200"
      fill="url(#a122407_rad1)" style="filter: url(#a122407_f1)">
  <ellipse cx="150" cy="260" rx="120" ry="200"
      fill="url(#a122407_rad1)" style="filter: url(#a122407_f1)">

參考資料 有趣的 SVG filter - 創造紋理

例題: 水波倒影

遍歷原圖形的所有像素點,使用feDisplacementMap重新映射替換一個新的位置,形成一個新的圖形。 因此,feDisplacementMap濾鏡在業界的主流應用是對圖形進行形變,扭曲,液化。
右圖就是兩個 <img>元件,其中下圖標是上圖標的垂直翻轉。
<img src="./moon-night.jpg">
<img src="./moon-night.jpg" class="reflect">
.reflect {
    transform: scaleY(-1);
    filter: url(#displacementFilter);
}
這裡同時應用了2個濾鏡,一個是feTurbulence濾鏡,模擬湍流。 其中baseFrequency的屬性值的水平和垂直的噪點頻率比是1:10,因此,會有類似水平拉伸的效果。

另一個 feDisplacementMap 濾鏡則根據 R(紅色)通道進行水平方向的位置偏移,根據 B(藍色)通道進行垂直方向位置偏移, 由於彩色湍流水平拉伸了,因此,最終的濾鏡效果就是一個水平方向拉伸為主的液化效果,視覺上就像是自然界水波蕩漾的效果。

<svg width="0" height="0" style="posiotion:absolute;left:-999px;">
  <filter id="displacementFilter">
    <feTurbulence type="turbulence" baseFrequency="0.01 .1"
        numOctaves="1" result="turbulence" seed="53" />
    <feDisplacementMap in2="turbulence" in="SourceGraphic"
        scale="20" xChannelSelector="R" yChannelSelector="B" />
  </filter>
</svg>

應用例題: 水波蕩漾

模擬水波倒影的基本作法和前例一樣。此例使用 SMIL 動畫元件 animate,調整濾鏡 feTurbulence 的 baseFrequency, 由 0.02 0.1 到 0.022 0.13 再回到 0.02 0.1,為時 15秒。如此不斷循環,即可造成水波蕩漾效果。更多動畫示例,見 SMIL。
<svg width="300" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
  <filter id="a122305_f1" filterUnits="userSpaceOnUse">
    <feTurbulence type="turbulence" baseFrequency="0.02 0.1"
         numOctaves="2" result="a122305_tt">
      <animate attributeName="baseFrequency"
          values="0.02 0.1;0.022 0.13;0.02 0.1" dur="15s"
          repeatCount="indefinite">
      </animate>
    </feTurbulence>
    <feDisplacementMap in2="a122305_tt" in="SourceGraphic" scale="40"
        xChannelSelector="R" yChannelSelector="G">
    </feDisplacementMap>
  </filter>
</defs>
  <image href="../svg/bird.jpg" x="-20" y="0" width="320" height="200"
     preserveAspectRatio="none"
     style="transform:translate(0,430px) scale(1,-1) ;    // 反轉
     filter: url(#a122305_f1)"></image>  // 倒影圖
  <image href="../svg/bird.jpg" x="-20" y="0" width="320" height="240"
  preserveAspectRatio="none"></image>  // 原圖
</svg>

又一水波蕩漾

參考說說SVG的 feTurbulence 濾鏡

應用例題: 水波漣漪


Click Me!

參考資料

關於製造水波效果的說明,請參考

<feBlend>

<feBlend> 用於通過各種簡單的方法(即模式屬性的值)將兩個圖像混合在一起。
混合的模式(mode)有 normal(正常)、screen(屏幕)、multiply(倍增)、lighten(變亮)和 darken(變暗)。
 <defs>
   <filter id="blend" x="0" y="0">
     <feImage xlink:href="../svg/qing-vase.jpg" width="50%" height="50%" result="rectangle" />
     <feImage xlink:href="../svg/strawberry-fields.jpg" width="50%" height="50%" result="strawberry" />
     <feBlend mode="darken" in="rectangle" in2="strawberry" />
   </filter>
 </defs>

 <g filter="url(#blend)">
<image x="5%" y="10%" href="strawberry-fields.jpg" height="100%" width="100%"/>
 </g>
另一示例
<rect x="0" y="0" height="100%" width="100%" fill="white"/>

<filter id="screen">
    <feBlend mode="screen" in2="BackgroundImage" in="SourceGraphic"/>
</filter>
<filter id="darken">
    <feBlend mode="normal" in2="BackgroundImage" in="SourceGraphic"/>
</filter>
<filter id="multiply">
    <feBlend mode="multiply" in2="BackgroundImage" in="SourceGraphic"/>
</filter>
<filter id="lighten">
    <feBlend mode="lighten" in2="BackgroundImage" in="SourceGraphic"/>
</filter>
<filter id="sample">
  < feBlend mode="darken" in2="BackgroundImage" in="SourceGraphic">
    <animate attributeName="mode"  dur="5s"
      values="screen;multiply;lighten;darken;"
      repeatCount="indefinite"/>
</feBlend>

<g enable-background="new">
<rect x="0" y="10%" height="4%" width="100%" fill="red"/>
<rect x="0" y="14%" height="4%" width="100%" fill="green"/>
<rect x="0" y="18%" height="4%" width="100%" fill="blue"/>
<image x="5%" y="5%" xlink:href="../svg/p2.jpg" filter="url(#darken)" height="46%" width="26%"/>
<image x="20%" y="5%" xlink:href="../svg/p2.jpg" filter="url(#screen)" height="46%" width="26%"/>
<image x="35%" y="5%" xlink:href="../svg/p2.jpg" filter="url(#multiply)" height="46%" width="26%"/>
<image x="50%" y="5%" xlink:href="../svg/p2.jpg" filter="url(#lighten)" height="46%" width="26%"/>
<image x="65%" y="5%" xlink:href="../svg/p2.jpg" filter="url(#sample)" height="46%" width="26%"/>
</g>
示例二

將兩圖混合,混合模式由左而右:normal, multiply, screen, darden, lighten

<filter id="lighten" x="0" y="0" width="200" height="250">
    <feImage width="200" height="250" xlink:href="girl.jpg" result="img1" />
    <feImage width="200" height="250" xlink:href="sky.jpg" result="img2" />
    <feBlend mode="lighten" in="img1" in2="img2"/>
</filter>

原圖位址

參考資料有意思!強大的 SVG 濾鏡

Blend modes for <feBlend>

雲破月來花弄影--SVG多種技術組合實現

月來

用svg做個月亮還是很簡單的,只要畫一個發光的大圓餅就好了。

<circle id="whitemoon" cx="420" cy="160" r="60" fill="white" />

用 feGaussianBlur 模糊後的作為月亮的光。

<filter id="blur-moon">  // 發光的月亮
    <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
</filter>

再應用 feTurbulence 和 feDisplacementMap製造月亮上的陰影:

<circle id="greymoon" cx="420" cy="170" r="30"
    fill="grey" fill-opacity="0.25"
    filter="url(#filter-greymoon)" />
<filter id="blur-greymoon" width="350%" height="250%" x="-100%" y="-100%">
     <feGaussianBlur in="SourceGraphic" stdDeviation="1" />
</filter>
<filter id="filter-greymoon" width="350%" height="250%" x="-100%" y="-100%">
    <feTurbulence type="fractalNoise"
        baseFrequency="0.03" numOctaves="9" seed="3" />
    <feDisplacementMap in="SourceGraphic" scale="120" />
</filter>

組合起來,就成為有陰影、邊緣發光的月亮。

<g id="moon">
<use xlink:href="#whitemoon" /> // 月亮
<use xlink:href="#whitemoon" filter="url(#blur-moon)" /> // 發光的月亮
<use xlink:href="#greymoon" filter="url(#greymoon)" />  // 有陰影的月亮
</g>
<use xlink:href="#moon" />

雲破

雲的製作分三段:前、中、後。每段大同小異,只是位置、大小和顏色不同。
以下以後段為例,主体是橢圓,應用 feGaussianBlur 糢糊化,再應用 feTurbulence 和 feDisplacementMap 雜亂化。注意,feTurbulence 的 type 用的是 fractalNoise。

<ellipse id="cloudback" cx="260" cy="130" rx="180" ry="50"
    fill="white" fill-opacity="0.95" filter="url(#blur-cloud)" />
<filter id="blur-cloud" width="350%" height="250%" x="-100%" y="-100%">
  <feGaussianBlur in="SourceGraphic" stdDeviation="15" />
</filter>
<filter id="filter-back" width="350%" height="280%" x="-100%" y="-100%">
    <feTurbulence type="fractalNoise" baseFrequency="0.012"
        numOctaves="4" seed="0" />
    <feDisplacementMap in="SourceGraphic" scale="140" />
</filter>
<use xlink:href="#cloudback" filter="url(#filter-back)" />

雲的製作參考天邊一朵雲

花弄影

feoffset:該輸入圖像作為一個整體,在屬性 dx 和屬性 dy 的值指定了偏移量。說白了就是把原圖在離開dx和dy的距離外複製一個一樣的圖像。
feBlend:把兩個對象組合在一起,使它們受特定的混合模式控制。選擇 darken 模式製造花影
<filter id="huazhishadow" x="0" y="0" width="300%" height="200%">
    <feOffset result="offOut" in="SourceAlpha" dx="220" dy="0" />
    <feGaussianBlur result="blurOut" in="offOut" stdDeviation="1" />
    <feBlend in="SourceGraphic" in2="blurOut" mode="darken" />
</filter>
<image xlink:href="../svg/huazhi.png" x="200" y="10" width="100"></image>
<image xlink:href="../svg/huazhi.png" x="-90" y="10" width="130"
   filter="url(#huazhishadow)" transform="skewX(29)"></image>

雲破月來花弄影

最後把月亮,雲、院牆和花影組合起來,並調整彼此位置,成為最終的影像。

<image xlink:href="yuanqiang.png" x="0" y="50" width="400"/>  // 院牆
<use xlink:href="#moon" />  // 月亮
<use xlink:href="#cloud" />  // 雲
<image xlink:href="huazhi.png" x="200" y="400" width="100"> // 花
<image xlink:href="huazhi.png" x="-490" y="400" width="130" // 花影
   filter="url(#huazhishadow)" transform="skewX(29)"/>

逐步詳細解說,見雲破月來花弄影

==>svg-filters

參考資料

  1. SVG Filter Play
  2. Filter Effects in SVG
  3. svg filter
  4. SVG 完整教學 31 天
  5. 一次搞懂SVG中所有常用的濾鏡
  6. why-the-svg-filter-is-awesome
  7. The 10 Best SVG Filter Resources & Tutorials
  8. 強大的 SVG 濾鏡
  9. svg-filter-shadow-css-blur
  10. fediffuselighting
  11. SVG feTurbulence濾鏡深入介紹
  12. SVG fedisplacementmap濾鏡深入介紹
  13. outline-text-with femorphology