上篇:juejin.im/post/591272…
中篇:juejin.im/post/591514…瀏覽器
在前面兩篇文章中,雖然完整描述了任意圖形的變形動畫實現方法,但最大的侷限性顯而易見,那就是都是一個圖形變造成另外一個圖形,那若是是一變多或者多變一怎麼實現呢?下面就來解決這個問題。bash
以最簡單的例子來講明,我要作個一個水珠裂變成兩個水珠的動畫效果,裂變過程毫無疑問屬於圖形的變形過程。可是裂變以後分開成兩個的時候怎麼辦?這是咱們首要解決的問題。先說一下各類實現思路,而後進行對比。svg
咱們在前面說過用剪刀斷開錨點,使閉合路徑轉換成開放路徑,因此聰明的設計師小夥伴應該能夠想到,既然能夠斷開一個錨點,那就能夠再斷開一個,讓一條路徑變成兩條路徑,兩條路徑分別實現本身的動畫效果,換句話說,就是半個小水珠變成一個小水珠的變形動畫,以下圖所示工具
<path>
各調用一個變形動畫,代碼以下:
<svg>
<style>
@keyframes deform1{
0% {d:path('');} /*變形前左半個水滴的路徑*/
100% {d:path('');} /*變形後左邊水滴的路徑*/
}
@keyframes deform2{
0% {d:path('');} /*變形前右半個水滴的路徑*/
100% {d:path('');} /*變形後右邊水滴的路徑*/
}
#animate1 {animation: deform1 2s ease;}
#animate2 {animation: deform2 2s ease;}
</style>
<path id="animate1"/>
<path id="animate2"/>
</svg>複製代碼
那看一下這種實現思路獲得的效果如何post
雖然表面上看實現了1變2,但一分爲二的過程極其生硬,主要緣由是咱們實現思路就是半個水滴到一個水滴,因此動畫過程徹底復現了咱們的思路。優化
上面方法實現的效果並很差,並且設想一下,這是變成2個,那若是是變成3個,4個呢,要把變形前的圖形切的稀碎麼……
既然咱們前面兩篇都是一變一的實現方法,那麼咱們不妨變通一下,好比變形前的水滴實際上有兩個徹底重合的圖形,一個變成左邊的,一個變成右邊的。實現思路以下:動畫
雖然兩個水滴是重合的,可是路徑方向那裏,向左變形和向右變形的原始路徑方向必定要是相反的,不然你將獲得下面這種效果(你甭說,就這種誤打誤撞的錯誤效果,作個打開的門啊,書啊的,竟然還不錯):url
先不要把這個方法一棍子打死,那是由於咱們變形先後的圖形形狀沒有變化,纔會產生位移效果,若是是作一個圓形變成兩個水滴,變形效果仍是有的,以下:spa
效果一點都不歡樂,直接暴露了咱們妄圖掩蓋的事實真相。
固然了,方法2雖然不是最佳,但某些情景下也是適用的。
不過咱們重磅推出的是下面這個方法。設計
此方法堪稱方法1和方法2的結合,咱們方法1是把原始形狀生生的切成兩半,那這個方法是咱們找變形後圖形一分爲二的那一瞬間,好比針對這個變形效果,就是兩個變形後水滴仍然相連的剎那,此時,仍然是一個圖形,動畫分解成兩個階段,第一階段,藕斷絲連,第二階段,快刀斬下。但在瞬間,運用了「障眼法」,來實現兩個過程的完美拼接。
那咱們要作的,就是在AI裏用路徑查找器,把臨界點的兩個形狀進行合併。我用圖示表示一下
<svg>
<style>
@keyframes deform1{
0% {d:path('');} /*原始水滴*/
100% {d:path('');}/*臨界點水滴*/
}
@keyframes deform2{
0% {d:path('');} /*重疊效果的左邊水滴*/
100% {d:path('');} /*移動位置後的左邊水滴*/
}
@keyframes deform3{
0% {d:path('');} /*重疊效果的右邊水滴*/
100% {d:path('');} /*移動位置後的右邊水滴*/
}
#animate1 {animation: deform1 1.5s cubic-bezier(0.8, 0, 0.85,0.5);}
#animate2 {animation: deform2 0.5s cubic-bezier(0.15, 0.5, 0.2, 1) 1.5s;}
#animate3 {animation: deform3 0.5s cubic-bezier(0.15, 0.5, 0.2, 1) 1.5s;}
</style>
<path id="animate1"/>
<path id="animate2"/>
<path id="animate3"/>
</svg>複製代碼
簡單解釋一下,2s的動畫效果我拆分紅2部分,前一部分變形效果1.5s,第二部分位移0.5s,但要延遲1.5s後執行,以實現時間上的無縫對接。
修改運動速率,是由於ease表示慢-快-慢,若是拼接動畫都使用這個運動速率,整個流程下來就是慢-快-慢-慢-快-慢,在臨界點那裏會有明顯的停頓感,所以我修正了運動速率以消除停頓效果。原本用了預約義的值,變形動畫爲ease-in(慢—快),而位移動畫爲ease-out(快-慢)。但發現銜接部分仍然不夠順滑,索性本身從新寫了速率曲線,說着嚇人,方法掌握以後其實很簡單,正好借這個案例說一下:
來看下效果如何:
小總結,之因此沒有從一開始就直接來方法3,是由於方法3費時最長,其實咱們須要的是越簡單的方法實現越理想的效果越好(拗口),因此在一些場景中,能用方法1和方法2(尤爲方便)來實現實則再好不過。
對於方法3這種尋找臨界點的圖形,則更適合精細化製做。
小技巧:因爲這類變形動畫涉及的形狀及位置比較多,爲了方便本身查看SVG代碼,實際展示的色值信息因爲是定義在CSS樣式中,因此建議做圖時定義成方便識別的顏色,或者建在不一樣圖層上,(AI導出的SVG會根據不一樣圖層進行分組)。
截止到這裏,咱們已經能夠實現無窮的變形效果了,裂變,組合,玩到嗨起來。但還有一種常見的圖形,須要單獨說一下實現變形動畫的方法,就是下面這種鏤空的圖形,此次的案例是從一把鑰匙變成一把鎖,只須要這一個案例作基礎,掌握方法以後,一通百通,原始圖片以下:
若是沒有鑰匙孔和鎖孔,這種變形動畫實現起來可謂簡單無比,但多了孔以後,貌似有點棘手,別急,先來看這種圖形(AI中須要合併形狀)d值的面目。因爲案例圖形太過複雜,咱們仍是從最簡單的入手。
這裏借用之前提到的蒙版來試一下。
UI設計師對於蒙版絲絕不陌生,SVG蒙版的原理是同樣的,鏤空部分我用黑色蒙版來處理,達到一樣的效果。
思路以下:動畫拆解成兩部分,一部分是無鏤空部分的圖形的變形動畫,另外一部分我把變形動畫附加給蒙版黑色部分,即咱們要鏤空的區域。
<svg>
<style>
@keyframes deform1{
0% {d:path('');}/*變形前底圖*/
100% {d:path('');}/*變形後底圖*/
}
@keyframes deform2{
0% {d:path('');}/*變形前蒙版黑色部分*/
100% {d:path('');/*變形後蒙版黑色部分*/
}
}
#animate1 {animation: deform1 3s ease;}/*
底圖變形動畫*/
#animate2 {animation: deform2 3s ease ;fill:#000000;}/*
蒙版黑色區域變形動畫*/
</style>
<mask id="hollow"><rect x="0" y="0" fill="#ffffff" width="" height=""/><path id="animate2" /></mask><!--定義一個白色矩形爲底,黑色爲變形動畫的蒙版hollow-->
<path id="animate1" mask="url(#hollow)"/><!--底圖變形動畫上附加一個蒙版變形動畫-->
</svg>複製代碼
看到這裏,沒有任何SVG蒙版基礎的UI設計師或許會有些發憷,但仍是但願瞭解一下,由於蒙版動畫很強大,後面會開單獨的專題。
來看一下利用蒙版變形結合底圖變形的動畫效果如何:
前面提到過,把蒙版動畫單獨定義自由度更高,好比,我再給蒙版變形動畫增長一個50%的關鍵幀,而後縮小成極小的一個點,動畫效果就變成了下面這種:
咱們對圖形的操做一直說的都是錨點手柄部分處理,一直想避開這部分,主要是考慮到UI設計師畢竟對AI軟件更熟悉,操做起來更方便,而是我在作案例的實際操做過程當中,發現對於錨點較少的狀況還好,找對應路徑也能順利找到,而在我上面鑰匙和鎖變形動畫中(20個錨點),即便經過d值看出來有些曲線時非小c開頭的,但數起來真的很困難,因此額外增長這一部分,能夠直接經過修改d值實現同一成小c曲線轉換的方法。只說方法,不說原理哦。
先說最容易出現的小s,看過上篇的設計師們已經知道產生小s的方法是由於轉換點直接拖拽,並且s後面只有四個值,轉化方法以下:
sA,B,C,D←→c前一組倒數第二個數減去倒數第四個數,前一組倒數第一個數減去前一組倒數第三個數,A,B,C,D
啊啊啊,頭暈了對不對,這仍是僅限於前面是正常一組小c開頭的曲線的轉換公式,因此除非你只有極個別小s出現,不然多算傷身啊。
設計師小夥伴們必定擦亮眼睛,由於小l與數字1太像,但只要記得咱們的d值只支持一位小數,而出現相似3.51這樣的數據時,那必定是3.5和小l。小l是繪製直線的命令,後面只有兩個值,轉換方法以下:
lA,B←→c0,0,A,B,A,B
前面補兩個0,後面複製一組小l後面的兩個值。
小l和小s最多見,下面這兩個則出現的狀況少一些,一點出現,建議改一下圖形,爲什麼,來看轉化方法。
h爲水平直線繪製命令,後面只有一個值,轉換方法以下:
hA←→c0,0,A,前一組路徑曲線小c的最後一個值,A,前一組路徑曲線小c的最後一個值
v爲垂直直線繪製命令,同上同理,轉換方法以下:
vA←→c0,0,前一組路徑曲線小c的倒數第二個值,A,前一組路徑曲線小c的倒數第二個值,A
看,誠不欺你,因此爲了避免給本身製造困難,稍微挪挪錨點,不要那麼水平垂直的直來直去嘛。
還有出現的狀況是絕對定位大寫字母開頭的,這個轉換起來,嘖嘖,反正不借助工具,我是不能接受手動計算的。
就醬。
藉助公式,順便作個動畫效果看看。
d:path('M60,490,c0,0,50,0,50,0,c0,0,100,0,100,0,c0,0,50,0,50,0,c0,0,50,0,50,0,c0,0,50,0,50,0,c0,0,50,0,50,0')複製代碼
這就是相對座標的好處,c0,0,50,0,50,0,表示一根水平的寬度50的直線,對應蘑菇的6段曲線,重複6次就OK了。
再來一根直線變飛鳥與魚的,哦,不是飛鳥,是肥鳥。把前面的知識點藉機再嘮叨一遍。順便帶出來壓箱底的技能,虛擬曲線。先賣個關子。
d:path('M40,130,c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,280,0,280');複製代碼
其實這個效果和
d:path('M40,130,c0,0,0,280,0,280');複製代碼
是同樣的,咱們只是在欺騙瀏覽器,製造一些不存在的曲線以便彌補變形先後圖形曲線數量的不一樣。
動畫能夠拆成兩部分,銜接起來,也能夠像我這樣在一個動畫裏完成,因爲最終小胖鳥的曲線數量最多,多以最終我給直線補充了8段虛擬曲線,給小魚補充了5段(所有放到魚嘴的位置),而後看一下效果
是否是感受太簡單了,並且很憤怒的指出來,爲何到最後才說這種簡單好用的方法?!勿燥,理由很簡單,加錨點是爲了讓變形的過程變得均勻。好比個人小鳥變成魚,若是是經過分散添加錨點來實現,效果是下面這樣的:
d:path('M60,490c0,0,150,0,150,0c0,0,150,0,150,0')複製代碼
而後把須要增長的4條虛擬曲線塞進去,位置就是中心點,也就是第一段路徑後面。
d:path('M60,490c0,0,150,0,150,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,0,0,0,0c0,0,150,0,150,0')複製代碼
好了,看看是否是從中心點長出的蘑菇:
svg描邊動畫效果在別的文章裏介紹過,利用路徑變形動畫依舊能夠完成,只不過這只是種「僞描邊」,更像是從某個點輻射出去的效果,看一下下面這個動畫:
<svg>
<style>
@keyframes deform1{
0% {d:path('');} /*花莖變形前虛擬點*/
100% {d:path('');}/*花莖曲線路徑*/
}
@keyframes deform2{
0% {d:path('');}/*左邊葉子變形前虛擬點*/
100% {d:path('');}/*左邊葉子曲線路徑*/
}
@keyframes deform3{
0% {d:path('');}/*右邊葉子變形前虛擬點*/
100% {d:path('');}/*右邊葉子曲線路徑*/
}
@keyframes deform4{
0% {d:path('');}/*花朵變形前虛擬點*/
100% {d:path('');}/*花朵曲線路徑*/
}
#animate1 {animation: deform1 1s ease forwards;}/*長出花莖時間1s,forwards表示動畫狀態停留在結束狀態*/
#animate2 {animation: deform2 1s ease 1s forwards;}/*長出左邊葉子時間1s,延遲1s(即花莖動畫時間)開始*/
#animate3 {animation: deform3 1s ease 2s forwards;}/*長出右邊葉子時間1s,延遲2s(即花莖+左邊葉子動畫時間)開始*/
#animate4 {animation: deform4 1s ease 3s forwards;}/*開花時間1s,延遲3s(即花莖+左邊+右邊葉子動畫時間)開始*/
</style>
<path id="animate1"/>
<path id="animate2"/>
<path id="animate3"/>
<path id="animate4"/>
</svg>複製代碼
這裏再提供一個轉換方法,就是關於絕對位置大C繪製路徑。若是你導出的d值中有大C開頭的曲線,關於這種經過虛擬點變形的話,就沒有必要再去調整路徑了。
c0,0,0,0,0,0等同於CX1,Y1,X1,Y1,X1,Y1。X1和Y1就是你的起始點M值的座標。關於SVG路徑path的貝塞爾曲線繪製方法的介紹網上不少,耐心看一遍就知道轉換的緣由了。
實際使用過程當中,必定要把握的思路是儘可能用最簡單的方法來實現動效,已經開始着手準備寫一篇SVG微動效的文章,畢竟SVG結合CSS3實現的動畫不可與真正的動畫製做軟件同日而語,應用最多的場景,應該是一些微動效。這篇做爲變形動畫的進階篇,涉及的知識點比較雜,包括拼接動畫臨界點的定義及自定義速率曲線實現無縫拼接的方法,結合蒙版變形動畫實現變形動畫,非小c開頭的路徑曲線的轉化,添加虛擬曲線。變形動畫全篇終。有問題單獨留言。