博客 / 詳情

返回

《SVG 動畫開發實戰》 - 🖼️ SVG 圖案動畫(Pattern)

🖼️ SVG 圖案動畫(Pattern)

想要在Web頁面中繪製背景圖案,我們首先可能想到的是使用 CSS,可能你也有所嘗試,比如簡單的漸變到複雜的網格、點陣等,SVG 中也有繪製背景圖案的解決方案。

SVG 中 fill 屬性支持以 pattern 方式填充一個圖案,Pattern 也是一個強大的元素聲明,如果圖案設計的比較完美,那麼會輕易得到一個無縫銜接的圖案。像這樣:

chapter9-1

原理

在 Web 頁面開發中如果想使用 SVG 生成背景,實際上有兩種使用方法:

SVG Pattern

一個純 SVG Pattern 使用的過程大致如下:

  1. 在 SVG 中聲明一個 pattern 元素
  2. pattern 中要聲明我們想要繪製的圖形
  3. 創建一個新的圖形,使用 SVG 中的 fill 屬性,填充圖案

代碼例子:

<svg width="360" height="240">
  <!-- defined a pattern for canvas -->
  <defs>
    <pattern id="rect" patternUnits="userSpaceOnUse" width="60" height="60">
      <rect width="30" height="30" fill="#4af" :x="range" :y="range"></rect>
    </pattern>
  </defs>
  <!-- simulate the pattern area -->
  <rect width="60" height="60" stroke="#a4f" stroke-width="2" fill="none" />
  <!-- fill pattern into canvas -->
  <rect id="canvas" width="360" height="240" stroke="#aaa" fill="url(#rect)" />
</svg>

上面代碼會得到如下圖形,藍色方塊就是我們聲明的 pattern (圖案),圖案區域大小為 60 60 (單位 px),下圖以紫色邊框模擬一個圖案的大小範圍,圖案就會以這樣重複填滿整個 360 240 的圖形區域,形成一個大的圖案。

chapter9-2

💡 可以在 CodePen 上進行嘗試 👇

https://codepen.io/xiaoluobod...

SVG as background-image

這種方法其實是結合 CSS 使用 SVG ,過程如下:

  1. 創建好一個 SVG 圖形,無需聲明 pattern 元素
  2. 使用 background-image 引入 Base64 轉碼過的 Data-URI

代碼看起來像這樣:

.bg {
  background-image: url("data:image/svg+xml;%3csvg.../svg%3E");
}

以上面例子為基礎,編寫一個 SVG as background-image 版本:

💡 可以在 CodePen 上進行嘗試 👇

https://codepen.io/xiaoluobod...

這裏 SVG 轉 Data-URI 使用這個工具:URL-encoder for SVG

實戰

在 《CSS 揭秘》這本書中介紹複雜的背景圖案(網格)時,作者展示了僅用4行代碼,即可生成一幅簡單的網格圖案,也就是本篇文章的題圖,如果要使用 SVG 繪製相同的圖案的話,代碼行數未見得會比純 CSS 少。我們來做下對比:

網格圖案 CSS 版

<div class="grid-pattern"></div>
body {
  margin: 0;
}

.grid-pattern {
  height: 100vh;
  width: 100vw;
  border: 1px solid #fff;
  background-color: #269;
  background-image: linear-gradient(white 2px, transparent 2px),
    linear-gradient(90deg, white 2px, transparent 2px),
    linear-gradient(rgba(255,255,255,.3) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.3) 1px, transparent 1px);
  background-size: 100px 100px, 100px 100px, 20px 20px, 20px 20px;
  background-position: -2px -2px, -2px -2px, -1px -1px, -1px -1px;
}

書中作者使用的是巧妙的漸變 + 位置控制實現網格效果。

💡 可以在 CodePen 上進行嘗試 👇

https://codepen.io/xiaoluobod...

網格圖案 SVG Pattern 版

<svg width="100%" height="100%">
  <defs>
    <pattern id="rect" patternUnits="userSpaceOnUse" width="100" height="100">
            <!-- defined the shape -->
      <rect width='100' height='100' fill='#269'/>
      <g fill='#6494b7'>
        <rect width='100' height='1' y='20'/>
        <rect width='100' height='1' y='40'/>
        <rect width='100' height='1' y='60'/>
        <rect width='100' height='1' y='80'/>
        <rect width='1' height='100' x='20'/>
        <rect width='1' height='100' x='40'/>
        <rect width='1' height='100' x='60'/>
        <rect width='1' height='100' x='80'/>
      </g>
      <rect width='100' height='100' fill='none' stroke-width='2' stroke='#fff'/>
    </pattern>
  </defs>
  <rect id="canvas" width="100%" height="100%" fill="url(#rect)" />
</svg>

我們這裏使用 SVG Pattern 實現上面一樣的網格,實現思路就完全不同了。需要繪製多個基本圖形矩形。來達到目的。但是生成整個圖案的核心思想還沒有變,先構建一個可複製的最小形狀,然後讓它重複填充滿整個區域。

💡 可以在 CodePen 上進行嘗試 👇

https://codepen.io/xiaoluobod...

本章我們介紹過,SVG 有兩種實現圖案的方式,另一種 SVG as Background Image 的方式就由你來進行實驗。這裏不進行介紹了。

既然使用 CSS 創建的背景更簡單,那麼我們為什麼還要使用 SVG 呢,其實是因為 SVG 創建的圖形是矢量的。可控性更強,尤其是要寫動畫時。我們可以基於 SVG 圖案實現一些複雜的動畫效果。

動態的背景圖案

假設我們讓一個黑白格的類似棋盤的背景圖案動起來

chapter9-3

這個動畫很簡單,結合背景色的變化,讓矩形元素 scale 到很小,再彈回來。小心看久了被催眠,眼暈。😂

其實在製作背景圖案動畫時,我只需考慮如何讓 SVG Pattern 元素內的圖形動起來即可。至於剩餘的都是重複了一個 pattern 的動效模式,製造出一個龐大的整體動效。

💡 可以在 CodePen 上進行嘗試 👇

https://codepen.io/xiaoluobod...

優秀的 SVG Pattern 類庫

  • Hero Pattern
  • Trianglify.io
  • http://btmills.github.io/geopattern/

參考

  • https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Patterns
  • https://css-tricks.com/snippets/svg/svg-patterns/

關於

本文是《SVG 動畫開發實戰》 系列文章第九章。

Notion 版本

小冊是在 Notion 上完成撰寫的,所以我保留了 Notion 的分享版本,你也可以點擊這裏查看。

GitHub 版本

小冊提供了 GitHub 版本的在線閲讀體驗,傳送門

微信公眾號版本

關注我的技術公號,同樣也可以找到此小冊系列,目前在更新中。。。

xiaoluoboding

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.