Translate

2020年12月10日 星期四

有趣的 SVG filter

SVG 有個強大的 filter , 可以做到很多有趣的特效,先從最基本的開始

filter

x,y,width,height   濾鏡位置和大小,如果沒有設定,預設為使用該濾鏡的物件往外擴 10%

filterUnits        userSpaceOnUse 範圍為整個 SVG 
                   objectBoundingBox 範圍只在物件區域 (預設)
primitiveUnits     userSpaceOnUse  (預設)
                   objectBoundingBox 

feImage , feTile 和 feBlend

feImage 很單純的就是用一張圖當作過濾器,於是不管本來的圖長什麼樣子,都會變成那張圖,加上 feTile 後,有點像材質貼圖, 會佔滿本來圖形的 box 範圍

而 feBlend 是混合兩張圖, 可以指定 in 和 in2 以及 mode

in , in2     輸入的圖 
             SourceGraphic    用來過濾的原始圖
             SourceAlpha      原始圖的 alpha 
             BackgroundImage
             BackgroundAlpha
             FillPaint
             StrokePaint
             [filter-primitive-reference]

mode         multiply        兩張圖用 and 運算
             color-dodge     一種混色運算
             沒有值           直接疊圖

所有 filter 都可以用的參數

result       濾鏡後的結果
x,y          濾鏡影響座標
width,height 濾鏡影響範圍

<svg width="0" height="0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <filter id="a121011_fimg" x="0" y="0" width="100%" height="100%">
      <feImage xlink:href="https://yiharng.github.io/bird.jpg" width="100" height="100" preserveAspectRatio="none"></feImage>
    </filter>
    <filter id="a121011_ftile" x="0" y="0" width="100%" height="100%">
      <feImage xlink:href="https://yiharng.github.io/bird.jpg" width="100" height="100" preserveAspectRatio="none"></feImage>
      <feTile></feTile>
    </filter>
    <filter id="a121011_fblend" x="0" y="0" width="100%" height="100%">
      <feImage xlink:href="https://yiharng.github.io/bird.jpg" width="100" height="100" preserveAspectRatio="none"></feImage>
      <feTile></feTile>
      <feBlend in2="SourceGraphic" mode="multiply"></feBlend>
    </filter>
    <filter id="a121011_fblend1" x="0" y="0" width="100%" height="100%">
      <feImage xlink:href="https://yiharng.github.io/bird.jpg" width="100" height="100" preserveAspectRatio="none"></feImage>
      <feTile></feTile>
      <feBlend in2="SourceGraphic" mode="color-dodge"></feBlend>
    </filter>
    <path id="a121011_p1" d="M0,50 a1,1,0,0,1,100,0 a1,1,0,0,1,100,0 C200,110,150,150,100,180 C50,150,0,110,0,50Z" fill="#c00"></path>
  </defs>
</svg>
<div style="display:inline-block">
圖1:<br>原始的 path<br>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <use xlink:href="#a121011_p1"></use>
</svg>
</div>
<div style="display:inline-block">
圖2:<br>使用 feImage<br>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <use xlink:href="#a121011_p1" style="filter:url(#a121011_fimg);"></use>
</svg>
</div>
<div style="display:inline-block">
圖3:<br>feImage+feTile<br>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <use xlink:href="#a121011_p1" style="filter:url(#a121011_ftile);"></use>
</svg>
</div>
<div style="display:inline-block">
圖4:<br>feBlend mode="multiply"<br>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <use xlink:href="#a121011_p1" style="filter:url(#a121011_fblend);"></use>
</svg>
</div>
<div style="display:inline-block">
圖5:<br>feBlend mode="color-dodge"<br>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <use xlink:href="#a121011_p1" style="filter:url(#a121011_fblend1);"></use>
</svg>
</div>
圖1:
原始的 path
圖2:
使用 feImage
圖3:
feImage+feTile
圖4:
feBlend mode="multiply"
圖5:
feBlend mode="color-dodge"

feOffset

很單純的濾鏡,就是位移

  dx,dy    座標位移
  in       來源

利用 in="SourceAlpha" 可以取得陰影部位


<svg width="300" height="300" viewBox="-50 -50 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <defs>
    <filter id="a121012_offset" x="-50" y="-50" width="300" height="300">
      <feOffset dx="50" dy="50" in="SourceGraphic"></feOffset>
    </filter>
    <filter id="a121012_offset1" x="-50" y="-50" width="300" height="300">
      <feOffset dx="-50" dy="50" in="SourceAlpha"></feOffset>
    </filter>
    <path id="a121012_p1" d="M0,50 a1,1,0,0,1,100,0 a1,1,0,0,1,100,0 C200,110,150,150,100,180 C50,150,0,110,0,50Z" fill="#0afa"></path>
  </defs>
  <use xlink:href="#a121012_p1" stroke="#f00" stroke-width="5"></use>
  <use xlink:href="#a121012_p1" filter="url(#a121012_offset)"></use>
  <use xlink:href="#a121012_p1" filter="url(#a121012_offset1)"></use>
</svg>  

利用 feBlend 結合兩張圖產生單一濾鏡的陰影效果
filter 的每個效果後面可以加上 result="名稱" , 然後 in="名稱" 以及 in2="名稱" 來使用


<svg width="300" height="300" viewBox="-50 -50 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <defs>
    <filter id="a121013_offset" x="-50" y="-50" width="300" height="300">
      <feOffset dx="-30" dy="30" in="SourceAlpha" result="a121013_rr1"></feOffset>
      <feOffset dx="30" dy="30" in="SourceAlpha" result="a121013_rr2"></feOffset>
      <feBlend in="SourceGraphic" in2="a121013_rr1" result="a121013_kk1"></feBlend>
      <feBlend in="a121013_kk1" in2="a121013_rr2"></feBlend>
    </filter>
    <path id="a121013_p1" d="M0,50 a1,1,0,0,1,100,0 a1,1,0,0,1,100,0 C200,110,150,150,100,180 C50,150,0,110,0,50Z" fill="#0af"></path>
  </defs>
  <use xlink:href="#a121013_p1" filter="url(#a121013_offset)"></use>
</svg>  

feMerge , feMergeNode

feBlend 只能疊兩張圖,另一個疊圖用的是 feMerge

使用方式:由 feMergeNode 前後來調整順序

  <feMerge>
    <feMergeNode />
    <feMergeNode in="SourceGraphic" />
  </feMerge>

範例 :


<svg width="300" height="300" viewBox="-50 -50 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <defs>
    <filter id="a121014_offset" x="-50" y="-50" width="300" height="300">
      <feOffset dx="20" dy="20" in="SourceAlpha" result="a121014_m1"></feOffset>
      <feOffset dx="-20" dy="20" in="SourceAlpha" result="a121014_m2"></feOffset>
      <feMerge>
        <feMergeNode in="a121014_m1"></feMergeNode>
        <feMergeNode in="a121014_m2"></feMergeNode>
        <feMergeNode in="SourceGraphic"></feMergeNode>
      </feMerge>
    </filter>
    <path id="a121014_p1" d="M0,50 a1,1,0,0,1,100,0 a1,1,0,0,1,100,0 C200,110,150,150,100,180 C50,150,0,110,0,50Z" fill="#0af"></path>
  </defs>
  <use xlink:href="#a121014_p1" filter="url(#a121014_offset)"></use>
</svg>

feGaussianBlur

就是高斯模糊

  in              來源
  stdDeviation    模糊程度

範例 :


<svg width="300" height="300" viewBox="-50 -50 300 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa">
  <defs>
    <filter id="a121015_blur" x="-50" y="-50" width="300" height="300">
      <feGaussianBlur in="SourceGraphic" stdDeviation="15"></feGaussianBlur>
    </filter>
    <path id="a121015_p1" d="M0,50 a1,1,0,0,1,100,0 a1,1,0,0,1,100,0 C200,110,150,150,100,180 C50,150,0,110,0,50Z" fill="#0af"></path>
  </defs>
  <use xlink:href="#a121015_p1" filter="url(#a121015_blur)"></use>
/&gt;
</svg>
/>

feFlood

功能很單純的填滿一個距形的顏色,在這個範例中,特別說明一下濾鏡預設的範圍

黑框為本來物件的範圍,左上角為 (50,50) 而綠色濾鏡的大小從 (0,0) 開始畫,大小佔滿整張圖,結果影響範圍是本來的 rect 上下左右都加大 10% ,如紅框一樣,第二個藍色濾鏡從 (80,60) 開始畫


<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="background-color:#ffa;">
  <defs>
    <filter id="a121016_flood">
      <feFlood x="80" y="60" width="200" height="200" flood-color="#0af" flood-opacity="1"></feFlood>
    </filter>
    <filter id="a121016_flood1">
      <feFlood x="0" y="0" width="200" height="200" flood-color="#0fa" flood-opacity="1"></feFlood>
    </filter>
  </defs>
  <rect x="50" y="50" width="100" height="100" filter="url(#a121016_flood1)"></rect>
  <rect x="50" y="50" width="100" height="100" filter="url(#a121016_flood)"></rect>
  <rect x="50" y="50" width="100" height="100" stroke="#000" fill="none"></rect>
  <rect x="40" y="40" width="120" height="120" stroke="#f00" fill="none"></rect>
</svg>

沒有留言:

張貼留言