UI設計師福利之手把手作一枚不同凡響的loading動圖

SVG動畫本質上是動圖,咱們並不能把它當作實現真正動畫的工具,它比gif動圖的優點在於小的體量,可交互,可矢量放大,方便修改色值,但它的劣勢也很明顯,渲染須要耗內存(因此能用基本的移動旋轉等等實現就不要用路徑變形),並且移動端應用須要第三方框架,即便web應用還要考慮到瀏覽器的支持(千刀萬剮的ie),UI設計師也不是專業的動畫設計師,因此關於SVG動畫的應用,更多的是在一些微交互的細節上,好比如今要說的loading動圖,就是其中一個應用場景。
關於加載時的動圖,最多見的菊花已經被用濫了,在最開始接觸SVG的時候,爲了練手,作過一堆,以下:javascript

各類樣式的loading動圖

這些都是最基本的樣式,即便眼花繚亂,但實現起來都簡單無比,無非就是旋轉+寬高變化+位移。當你有充裕的時間,能夠考慮多花費一點精力來打造一枚獨一無二的loading圖標。融入一點品牌或產品的調性,在小細節處體現一下設計感。下面由淺入深,步步拆解,看一枚特別的loading動圖的作法。(老規矩,會附上能夠複用的代碼,方便UI設計師拿去用)

基本效果

先看一下下面這個動圖css

圓環長度變化

這裏面是兩個動畫屬性疊加,一個是旋轉,一個是圓周的長度由0增長到所有周長。CSS樣式部分代碼以下:

@keyframes animate {
0%{stroke-dashoffset:943;transform:rotate(0)}
100%{stroke-dashoffset:0;transform:rotate(360deg)}
}
#load{
animation:animate 2s  ease infinite;
transform-origin:center center;/*定義旋轉的原點*/
stroke-dasharray:943;/*計算獲得的圓周周長*/
stroke-width:20px;/*圓形的描邊各類屬性值*/
stroke:#8879aa;
stroke-linecap: round;
fill:none
}複製代碼

描邊長度逐漸增長用虛線偏移位置stroke-dashoffset配合虛線樣式stroke-dasharray來實現是最合適不過,第一次接觸描邊動畫能夠參考個人這篇文章 UI福利,svg描邊動畫效果,零代碼基礎手把手教你完成 www.jianshu.com/p/a3d66a920…
這裏面注意一下圓形周長的計算,其餘就是套用。
旋轉動畫就比較乏善可陳了,最基本的用法。
而後用<circle>標籤引用load屬性(id="load")就能夠實現這種長短變化+旋轉的動效。
瞭解了這些,就能夠看一枚不同凡響的loading圖標了java

創意來源

創意來源

這是我在dribbble看到的一枚圖標,當時就震驚了,原來除了那些千篇一概的加載圖標,這貨竟然還能夠作成這樣!也深深的感慨到本身的差距,空有一些技法,但創意渣到空白。
不過既然看到了,那就想個方法來實現這種效果。先模仿再創新嘛。
先說這個cat的選取,很恰到好處,原本喵星人的身體就有這種拉伸的屬性,你能想象若是換成一頭身子被拉伸的大象嘛?固然了,這也致使我在模仿這枚圖標的時候思索了很久,不過仍是選了我喜歡的一頭小獅子。效果差強人意。

底圖

個人底圖就是上面這隻可愛的小獅子,我想象中的效果是獅子被分割成3部分,頭(A)+身體(B)+尾巴(C)。旋轉的過程就是身體拉伸的過程。思路以下圖所示。web

動畫思路

改造底圖

爲了保證獅子身體拉伸時與頭部和尾巴實現無縫對接,要對小獅子進行一些小改造,把圓弧的一段嵌入到身體中。
首先在AI裏作一個圓形,描邊的粗度就是可伸縮的小獅子的身體,調整小獅子的大小和位置。瀏覽器

肯定好各個元素的位置

剩下的工做對於UI來講仍是比較簡單的,相同位置複製一個圓形,只取其中一小段弧形,進行擴展,由路徑變成形狀,調節獅子原來的身體,使圓弧可以徹底與頭部和尾巴契合。框架

調整

調整以後,原來小獅子的身體就由一段圓弧代替了,此時,再對小獅子的身體進行切割,前半部分與頭部組合,後半部分與尾巴組合。
至此,對於小獅子的改造所有完成。svg

不一樣運動速率的頭部和尾巴

根據前面的分析,咱們的頭部要走的快一點,尾巴要走的慢一點,這樣才能實現把身體拉伸的效果。
這裏有不一樣的方法來實現,我使用的方法是控制關鍵幀。代碼以下:工具

@keyframes right{
0%{transform:rotate(0); } /*定義頭部旋轉動畫*/
75%{transform:rotate(360deg);}/*頭部完成動畫時間1.5s(2*0.75s)*/
100%{transform:rotate(360deg); }
}
@keyframes left{
0%{transform:rotate(0); } /*定義尾巴旋轉動畫*/
100%{transform:rotate(360deg);}
}
#moveRight{animation:right 2s ease  infinite;transform-origin:300px 300px}/*旋轉中心點爲圓形原點*/
#moveLeft{animation:left 2s ease infinite;transform-origin:300px 300px}複製代碼

經過增長時間節點75%的關鍵幀,使頭部旋轉的動畫時間縮短爲定義時間2s的75%,即1.5s完成旋轉360度,而尾巴則是2s完成旋轉360度,從而實現頭部與尾巴的速度差,也就意味着頭部比尾巴提早0.5s到達終點。動畫

可伸縮的身體部分

關於可伸縮的身體部分是這個動效的重點,由於身體的伸縮要與頭部和尾巴保持一致才能組成一個無懈可擊的總體。
還記得最開始的那個長度從零增長到圓周長的紫色圓環吧,咱們利用的是stroke-dashoffset配合stroke-dasharray來完成的。這裏仍然利用這個原理來實現彈性伸縮的身體。思路以下:ui


首先我把一圈的身體作爲底圖,而後利用蒙版(不瞭解SVG蒙版動畫的小夥伴先看一下個人關於SVG蒙版動畫的文章)來實現。蒙版上分別畫兩條路徑,一條是白色,爲了露出身體底圖部分,運動速率與頭部保持一致,同時,一條爲黑色,運動速率落後於白色,爲了消除掉多餘的身體部分,運動速率與尾巴保持一致。形象一點來講,就是白色描邊蒙版在前面跑,後面黑色描邊蒙版在追趕,直到完成一個週期的運動。
對應的CSS部分以下:

/*定義白色描邊動畫,速度與頭部旋轉動畫保持一致*/
@keyframes middle{
0%{stroke-dashoffset:942.48}
75%{stroke-dashoffset:0}
100%{stroke-dashoffset:0}
}
/*定義黑色描邊動畫,速度與尾巴旋轉動畫保持一致*/
@keyframes middle2{
0%{stroke-dashoffset:942.48; stroke:#000000}
100%{stroke-dashoffset:0; stroke:#000000}
}
#moveMiddle{stroke-dasharray:942.48;animation:middle  2s ease infinite;}
#moveMiddle2{stroke-dasharray:942.48;animation:middle2 2s ease infinite;}
#base{fill:#f8b602;mask:url(#shade)}/*定義底圖樣式,並調用蒙版*/複製代碼

代碼部分以下:

<mask id="shade">
<path id="moveMiddle" fill="none" stroke="#ffffff" stroke-width="40" stroke-miterlimit="10" d=""/> <!--用以逐漸顯示底圖的白色蒙版-->
<path id="moveMiddle2" fill="none" stroke="#ffffff" stroke-width="40" stroke-miterlimit="10" d=""/> <!--用以消除的黑色蒙版-->
</mask><!--以上蒙版的兩個d值相同,均爲圓形對應的路徑-->
<path id="base" d=""/> <!--d值爲組成身體底圖的路徑-->
<g id="moveLeft" >此處若干組成頭部的代碼……</g>
<g id="moveRight" >此處若干組成尾巴的代碼……</g>    複製代碼

這裏須要注意,個人動態描邊蒙版的路徑(圓形)被我從獅子身體位置斷開,以便控制描邊動畫的起點/終點。加上個好看的底色看一下效果:

loading lion

喲,看這彈性無比的身體。看這無縫拼接,完美啊。
打住,既然作都作了,這裏咱們要繼續深刻研究一下各個參數的修改都會對動效產生什麼影響。

參數調整對動效的影響

這裏面除了小獅子轉圈的速度,那個咱們從代碼裏能一眼看出來,一圈是2s,咱們來看一下我定義的時間軸的75%的關鍵幀,若是修改爲其餘值,會對動效產生什麼影響。
其餘不變,我只把關鍵幀的時間點改爲50%看一下(記得白色描邊蒙版動畫與頭部是捆綁在一塊兒的,要改一塊兒改,不然可憐的小獅子就會出現身體斷開或者身體跑到頭部前面等等詭異的現象)效果。

頭部完成一圈旋轉動畫關鍵幀定義在50%

哎呀呀,小獅子你腫麼了,身體被拉長好多……是的,當咱們能理解這個關鍵幀的含義時,就會知道,當頭部和白色蒙版的旋轉一週的關鍵幀定義到50%時,意味着頭部在1s即50%就完成了一圈的旋轉動畫,剩下的50%在等尾巴跟上來,也就是說獅子的身體部分最長可被拉長到圓周的1/2。
那一樣當我把時間軸的關鍵幀定義爲90%時,效果是下面這樣的:

頭部完成一圈旋轉動畫關鍵幀定義在90%

小獅子的身體被拉長的很輕微。因此這裏代碼若是要複用的時候,各位UI設計師能夠根據實際狀況本身去調整關鍵幀的位置。

一個週期旋轉N圈

回頭再看看帶給咱們靈感的那隻喵星人,而後對比一下咱們的小獅子,最大的區別在哪裏,嗯,小獅子每一個動畫週期只旋轉了一週,而喵星人是兩週??
若是不考慮身體部分,甭說兩週,就是三週,四周,三千六百度空翻都沒有問題,由於咱們的選擇動畫rotate那裏能夠填角度。
好比我把旋轉動畫改爲下面這樣

@keyframes right{
0%{transform:rotate(0); }
75%{transform:rotate(720deg);} /*720度爲旋轉2圈*/
100%{transform:rotate(720deg); }
}
@keyframes left{
0%{transform:rotate(0); }
100%{transform:rotate(720deg);}
}複製代碼

爲了轉起來不頭暈,完成一個動畫週期的時間我一樣加倍了一下,改爲了4s。

#moveRight{animation:right 4s ease  infinite;transform-origin:300px 300px}
#moveLeft{animation:left 4s ease infinite;transform-origin:300px 300px}複製代碼

看一下頭部和尾巴是否是一個週期旋轉2圈

一個動畫週期旋轉2圈的小獅子

那比較難實現的就是身體部分了,咱們一直是讓描邊動態蒙版來完成的,而描邊路徑,除了作了一下斷開自定義起點,並無作其餘的操做,那怎麼讓描邊的路徑也能任意加倍呢?那個,暫時放棄。下午作了幾種嘗試,均已失敗了結,給圓形路徑加倍不是問題,最主要的問題就是黑色描邊一圈後徹底遮蓋住了下面的描邊效果。等有解決方法再更新。有空會嘗試用蒙版套蒙版的方法。

補充,方纔靈光一現,問題迎刃而解,這感受,彷彿被打通任督二脈,廢話不說了,直接說個人解決方法。
在作扇形掃描效果時,我用了白色蒙版圍繞底圖的圓圈中心點旋轉方法,這裏解決方法相似,不過比那個還要簡單。

實現原理

我蒙版的創建是個「奧利奧」,上下黑色夾白色夾心。白色蒙版旋轉時黑色蒙版一直再追,設定幾圈就幾圈後追上。
看一下效果是否達到預期
雙層蒙版實現的彈性身體部分

哇,成功,徹底不受描邊動畫的那種限制。並且這個方法最合理的地方還在於能夠和頭部及尾巴動畫共用動畫設定。徹底實現了各類托馬斯旋轉。
在個人案例中,由於小獅子身體斷開的部分並非嚴格的圓形頂部,而是逆時針誤差了10度左右。這個AI就幫咱們處理了,當調整過角度以後,導出的矩形 <rect>標籤會有一個變形屬性transform="matrix()"。固然了,這裏我用的矩形,但實際使用過程,能夠用半圓形等等其餘形狀。
好了如今與獅子的頭部和尾巴合體!

旋轉2圈

既然這個方法快又好,那麼就放上基礎代碼並簡單註釋

<svg>
<style> /*定義頭部以及白色蒙版的旋轉動畫 旋轉度數能夠任意定義*/ @keyframes right{ 0%{transform:rotate(0); } 85%{transform:rotate(720deg);} 100%{transform:rotate(720deg); } } /*定義尾巴以及黑色蒙版的旋轉動畫*/ @keyframes left{ 0%{transform:rotate(0); } 100%{transform:rotate(720deg);} } /*因爲兩個元素調用相同動畫,因此定義成類*/ .moveRight{animation:right 4s ease infinite;transform-origin:300px 300px} .moveLeft{animation:left 4s ease infinite;transform-origin:300px 300px} /*定義底圖*/ #base{fill:#f8b602;mask:url(#shade)} </style>
<rect x="0" y="0" width="600" height="600" fill="#e5dcc5"/><!--圖形底色-->
<mask id="shade">
<rect x="0" y="0" width="600" height="600" fill="#000000"/><!--「奧利奧」蒙版的最底層黑色部分-->
<rect  fill="#ffffff" width="300" height="600" class="moveRight"/><!--「奧利奧」蒙版的中間層白色部分-->
<rect  fill="#000000" width="300" height="600" class="moveLeft"/><!--「奧利奧」蒙版的最上層黑色部分-->
</mask>
<path id="base" d=""/>
<g class="moveLeft" ><!--如下爲組成獅子頭部的代碼-->

</g>
<g class="moveRight"><!--如下爲組成獅子尾巴的代碼-->

</g>
</svg>複製代碼

有了基礎模板,修改起來就方便多了,好比我想實現轉3圈的效果,直接把transform:rotate(720deg)改爲transform:rotate(1080deg)就能夠了。
不過圈數越多,身體被拉伸的越厲害,能夠適當調整一下頭部的結束的關鍵幀,使速度變慢,好比我改爲92%後,就獲得了下面這種效果:

選擇3圈

各類隨意發揮,就醬,完美收工。

相關文章
相關標籤/搜索