🖼️ SVG 圖案動畫(Pattern)
想要在Web頁面中繪製背景圖案,我們首先可能想到的是使用 CSS,可能你也有所嘗試,比如簡單的漸變到複雜的網格、點陣等,SVG 中也有繪製背景圖案的解決方案。
SVG 中 fill 屬性支持以 pattern 方式填充一個圖案,Pattern 也是一個強大的元素聲明,如果圖案設計的比較完美,那麼會輕易得到一個無縫銜接的圖案。像這樣:
原理
在 Web 頁面開發中如果想使用 SVG 生成背景,實際上有兩種使用方法:
SVG Pattern
一個純 SVG Pattern 使用的過程大致如下:
- 在 SVG 中聲明一個
pattern元素 pattern中要聲明我們想要繪製的圖形- 創建一個新的圖形,使用 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 的圖形區域,形成一個大的圖案。
💡 可以在 CodePen 上進行嘗試 👇
https://codepen.io/xiaoluobod...
SVG as background-image
這種方法其實是結合 CSS 使用 SVG ,過程如下:
- 創建好一個 SVG 圖形,無需聲明
pattern元素 - 使用
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 圖案實現一些複雜的動畫效果。
動態的背景圖案
假設我們讓一個黑白格的類似棋盤的背景圖案動起來
這個動畫很簡單,結合背景色的變化,讓矩形元素 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 版本的在線閲讀體驗,傳送門
微信公眾號版本
關注我的技術公號,同樣也可以找到此小冊系列,目前在更新中。。。