SVG動畫本質上是動圖,咱們並不能把它當作實現真正動畫的工具,它比gif動圖的優點在於小的體量,可交互,可矢量放大,方便修改色值,但它的劣勢也很明顯,渲染須要耗內存(因此能用基本的移動旋轉等等實現就不要用路徑變形),並且移動端應用須要第三方框架,即便web應用還要考慮到瀏覽器的支持(千刀萬剮的ie),UI設計師也不是專業的動畫設計師,因此關於SVG動畫的應用,更多的是在一些微交互的細節上,好比如今要說的loading動圖,就是其中一個應用場景。
關於加載時的動圖,最多見的菊花已經被用濫了,在最開始接觸SVG的時候,爲了練手,作過一堆,以下:javascript
先看一下下面這個動圖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
個人底圖就是上面這隻可愛的小獅子,我想象中的效果是獅子被分割成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
/*定義白色描邊動畫,速度與頭部旋轉動畫保持一致*/
@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> 複製代碼
這裏須要注意,個人動態描邊蒙版的路徑(圓形)被我從獅子身體位置斷開,以便控制描邊動畫的起點/終點。加上個好看的底色看一下效果:
這裏面除了小獅子轉圈的速度,那個咱們從代碼裏能一眼看出來,一圈是2s,咱們來看一下我定義的時間軸的75%的關鍵幀,若是修改爲其餘值,會對動效產生什麼影響。
其餘不變,我只把關鍵幀的時間點改爲50%看一下(記得白色描邊蒙版動畫與頭部是捆綁在一塊兒的,要改一塊兒改,不然可憐的小獅子就會出現身體斷開或者身體跑到頭部前面等等詭異的現象)效果。
回頭再看看帶給咱們靈感的那隻喵星人,而後對比一下咱們的小獅子,最大的區別在哪裏,嗯,小獅子每一個動畫週期只旋轉了一週,而喵星人是兩週??
若是不考慮身體部分,甭說兩週,就是三週,四周,三千六百度空翻都沒有問題,由於咱們的選擇動畫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圈
那比較難實現的就是身體部分了,咱們一直是讓描邊動態蒙版來完成的,而描邊路徑,除了作了一下斷開自定義起點,並無作其餘的操做,那怎麼讓描邊的路徑也能任意加倍呢?那個,暫時放棄。下午作了幾種嘗試,均已失敗了結,給圓形路徑加倍不是問題,最主要的問題就是黑色描邊一圈後徹底遮蓋住了下面的描邊效果。等有解決方法再更新。有空會嘗試用蒙版套蒙版的方法。
補充,方纔靈光一現,問題迎刃而解,這感受,彷彿被打通任督二脈,廢話不說了,直接說個人解決方法。
在作扇形掃描效果時,我用了白色蒙版圍繞底圖的圓圈中心點旋轉方法,這裏解決方法相似,不過比那個還要簡單。
<rect>
標籤會有一個變形屬性transform="matrix()"。固然了,這裏我用的矩形,但實際使用過程,能夠用半圓形等等其餘形狀。
<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%後,就獲得了下面這種效果:
各類隨意發揮,就醬,完美收工。