olNGIb4NkK5r2x7x4oG3GpEzizVpnY6KNCck9cym

如何使用 CSS 的濾鏡(filter)屬性搭配 SVG 讓文字產生類似影印機複印的效果?

使用 CSS 的濾鏡(filter)屬性搭配 SVG 可以讓文字圖像產生類似影印機複印的效果。

筆者訪問 極客死亡計畫 時,除了讚嘆作者本身文章寫得很好之外,對於站點的樣式跟小細節也是十分喜歡。其中一部分讓我感到好奇的便是各級標題的樣式,有種看起來像是早期噴墨印表機列印出來的文字,或者是掃描的文件一般,帶有雜訊和扭曲的效果:

站點 '極客死亡計畫' 上的標題文字效果
站點 極客死亡計畫 上的標題文字效果
作者在其 Telegram 頻道「418.亡者茶話會」中的一則訊息提到,這個效果是從 endtimes.dev 借鑒來的。

筆者雖然不是專職的前端工程師,但畢竟活在有著強大開發者工具(DevTool)的幸福時代,簡單地使用該工具便能探究這個效果的堂奧。使用開發者工具檢視頁面上的任一標題元素時,可以發現有個名為 xerox 的類別(class)名稱,並且其 CSS 樣式使用了 filter 屬性:

有個名為 'xerox' 的類別(class)名稱,並且其 CSS 樣式使用了 'filter' 屬性
有個名為 xerox 的類別(class)名稱,並且其 CSS 樣式使用了 filter 屬性
.xerox {
    filter: url(#x);
}

根據 MDN 上關於 filter 屬性的說明,使用 url() 可以引用 SVG 過濾器元素,換句話說就是使用了 <filter> 的 SVG 元素,這可以實現許多的效果。

讓我們來檢查一下前面這個 #x 元素中寫了什麼:

<div style="display:none">
  <svg class="hidden">
    <filter id="x" height="500%">
      <feTurbulence baseFrequency="0.01 0.02" numOctaves="2" result="t0"></feTurbulence>
      <feDisplacementMap in="SourceGraphic" in2="t0" result="d0" scale="4"></feDisplacementMap>
      <feComposite in="SourceGraphic" in2="d0" operator="atop" result="0"></feComposite>
      <feTurbulence baseFrequency="1" numOctaves="2" result="t1"></feTurbulence>
      <feDisplacementMap in="0" in2="t1" result="d1" scale="1"></feDisplacementMap>
      <feComposite in="0" in2="d1" operator="atop" result="1"></feComposite>
      <feOffset dx="-3" dy="-3" in="1"></feOffset>
    </filter>
  </svg>
  <svg class="hidden">
    <filter id="xs">
      <feTurbulence baseFrequency="0.01 0.02" numOctaves="2" result="t0"></feTurbulence>
      <feDisplacementMap in="SourceGraphic" in2="t0" result="d0" scale="4"></feDisplacementMap>
      <feComposite in="SourceGraphic" in2="d0" operator="atop" result="0"></feComposite>
      <feTurbulence baseFrequency="1" numOctaves="2" result="t1"></feTurbulence>
      <feDisplacementMap in="0" in2="t1" result="d1" scale="1"></feDisplacementMap>
      <feComposite in="0" in2="d1" operator="atop" result="1"></feComposite>
      <feOffset dx="-3" dy="-3" in="1"></feOffset>
    </filter>
  </svg>
</div>

實際上在使用時,原站點將 SVG 元素包裹在了一個 <div> 元素中,並設定了 display: none; 使其避免在頁面中佔據區塊。而 SVG 中則是分別使用了以下關鍵部分:

  • feTurbulence 用於產生雜訊,其中以 baseFrequency 控制雜訊的頻率。
  • feDisplacementMap 用於產生扭曲,會以 feTurbulence 產生的雜訊來位移原始影像,並以 scale 控制扭曲強度。

實際上應用的效果如下:

我要殺死丁力那個雜碎!!
我要殺死丁力那個雜碎!!

可以觀察到由於這個樣式,應用的是整個文字的區塊,因此包含底線的效果也會帶有雜訊與扭曲。只能說 CSS 真是神奇又博大精深,太酷ㄌ!!

張貼留言