經常在Codepen上看到大俠們用 SVG 畫出不可思議的動畫,我一直很好奇他們是怎麼運作的,總覺得這需要對 SVG 有足夠透徹的了解,並且自己畫出那些 SVG 圖案,才有辦法讓他動起來。
但其實不然,今天教大家一個簡單的小技巧,讓你快速實現一個 svg 動畫!
打開Codepen,點擊界面中的build按鈕,就可以使用動畫構建一個房子,並且讓它升起寥寥炊煙!🏭
codepen[1]
尋找精美的 svg 圖案既然自己畫不出來,那我們就去找現成的庫,svg 庫有很多,如Flaticon[2]、iconfont[3]、Iconfinder[4]或icons8[5]等網站會提供很多免費的 svg 圖案。
分析 svg 圖案打開devtool觀察 svg 圖案,你會看到下面的結果:
element裡頭path跟circle都是 svg 的DOM元素,分別表示 svg 圖案內的線條與圓形。
舉個例子 🌰:
<path d="M 10 25
L 10 75
L 60 75
L 10 25">
複製代碼上面代碼中的 d 的內容:M 代表將筆移動到(10, 25),接著 L 畫一條線到(10, 75),最後回到起點畫出一個三角形。
通過 devtool,我們可以看到每個path對應圖案的哪個部分:
這時候應該形成思路,既然我們可以知道每個元素對應到圖案的哪個部分,我們就可以針對想要套上動畫的 DOM 元素來操作!TimelineLite/TimelineMax 工具如果單純通過 id、className 來使用 CSS 或 JavaScript 自行處理動畫,難度還是頗高,更重要的是,要耗費大量的時間
所以我們得借用工具,Timeline(Lite|Max)跟 TweenMax 是知名的GreenSock Animation Platform(簡稱 GSAP)[6]推出的可創建時間軸(timeline)作為動畫或其他時間軸的容器,這使得整個動畫控制和精確管理時間變得簡單。
GSAP 甚至為我們提供了Ease Visualizer[7]來展示每種 Ease function 的效果,更順帶附上代碼:
codepen[8]
簡單幾句代碼就能達到如下效果:
上手 GSAPGSAP 的 API 功能十分強大 👍,還有相關社區:官網文檔[9]、論壇[10]、TimelineMax 中文手冊[11]
在一開始的房子構建 🌰 中,我主要使用的是 TimelineMax 的from與staggerFrom,這兩個 API 只需要設定初始值,他會在指定時間內將補間動畫完成:
tl.from("#House > rect:nth-child(24)", 1, {
scaleX: 0,
transformOrigin: "center",
ease: Power2.easeOut
})
複製代碼這一步我們將 CSS Selector#House > rect:nth-child(24)這個元素,從scaleX為 0 開始,以 center(中心)為變形起點,利用Power2.easeOut,在一秒內回復到原始狀態,並執行補間動畫。
.staggerFrom(
["#House > path:nth-child(34)", "#House > path:nth-child(32)"],
0.8,
{
scaleY: 0,
transformOrigin: "bottom",
ease: Bounce.easeOut,
stagger: 0.2
},
0,
"scene1+=0.5"
)
複製代碼與from相似,只是staggerFrom可以一次放入多個 CSS Selector,用stagger這個屬性來設置數組中的 Selector 要以怎樣的時間差出現。
詳細 API 參數可以參考官方文檔[12]
接著回到我們的 SVG,在 devtool 的幫助下,要取出 svg 內部元素的CSS Selector非常容易,在 element 面板中找到對應的 DOM 元素點擊右鍵,選擇Copy -> Copy selector,就可以直接複製到該元素的 CSS Selector:
現在我們能取得 svg 中任意部分的 CSS Selector,也知道怎麼用 GSAP API 來進行補間動畫,現在是時候將其結合起來!
我們先調整下基本布局,一般在空白 Html 內直接放入 svg 時,圖案大多會緊靠頁面左上角,我們可以套用個margin: 0 auto將其置中,看起來會順眼一些,你也能額外加些 padding。我們在頁面添加一個按鈕來調用動畫:
<!--html part-->
<button onclick="animateBike()"> Build! </button>
<!--css part-->
<style>
#Capa_1 {
margin: 0 auto;
display: block;
width: 256px;
height: 100%;
}
</style>
複製代碼接著我們使用TimelineMax提供的staggerFrom函數,利用 devtool 將滑板車的輪子部分找出來,複製它們的 CSS Selector,放入staggerFrom函數參數中,設定 x 與 y 軸的scale都從 0 開始,由center增長,採用Bounce.easeOut的 ease function ,而四個 Selector 間以stagger: 0.2的屬性值作為補間動畫出現的時間差:
const tl = new TimelineMax();
tl.staggerFrom(
[
"#Capa_1 > g > path:nth-child(1)",
"#Capa_1 > circle:nth-child(7)",
"#Capa_1 > path:nth-child(6)",
"#Capa_1 > circle:nth-child(5)"
],
1,
{
scaleY: 0,
scaleX: 0,
transformOrigin: "center",
ease: Bounce.easeOut,
stagger: 0.2
}
)
複製代碼簡單幾行代碼,就能讓我們的滑板車動起來!
codepen[13]
補間是一個術語,用於描述逐幀序列,有時也稱為"中間"。在那個地方,一個動作導致下一個動作產生一個流暢的動作。
複製代碼
完善動畫你可以把 TimelineMax 想像成時間軸,動畫按指定順序執行,而staggerFrom則可以同時讓多個 DOM 元素以微小時間差的順序啟動,另外我們還可以設置一些 Flag 來指定要等到哪幾個動畫完成後,才接續其他動畫。
最後,發揮自己的創意,使用各種 API 打出一套組合拳 👊:
codepen[14]
結論 🎉看到這裡,躍躍欲試了嗎?
總之,我自己覺得蠻有趣的,希望或多或少對讀到這篇文章的人有點幫助。
最後給大家分享一個很酷的demo[15],來自我的文章封面
參考文章 📜[1] codepen: https://codepen.io/johnYu243/pen/bGBVEwv
[2] Flaticon: https://www.flaticon.com/
[3] iconfont: https://www.iconfont.cn/
[4] Iconfinder: https://www.iconfinder.com/
[5] icons8: https://icons8.com/
[6] GreenSock Animation Platform(簡稱 GSAP): https://greensock.com/
[7] Ease Visualizer: https://greensock.com/ease-visualizer/
[8] codepen: https://codepen.io/johnYu243/pen/jOVbMzX
[9] 官網文檔: https://greensock.com/docs/
[10] 論壇: https://greensock.com/forums/forum/11-gsap/
[11] TimelineMax 中文手冊: https://www.tweenmax.com.cn/api/timelinemax/
[12] 官方文檔: https://greensock.com/docs/v2/TimelineMax
[13] codepen: https://codepen.io/johnYu243/pen/poNjNzz
[14] codepen: https://codepen.io/johnYu243/pen/yLVYVey
[15] demo: https://www.zgzzsq.com/376658.html
[16] GreenSock Animation Platform: https://greensock.com/
[17] How to Create Beautiful SVG Animations Easily: https://medium.com/@LewisMenelaws/how-to-create-beautiful-svg-animations-easily-610eb2690ac3