前面的話
SVG動畫非常強大,只需要設置HTML元素,不需要CSS和JS,就可以實現動畫效果。本文將詳細介紹SVG動畫
概述
動畫實際上就是值關於時間的一個函數。在這個函數中,包含起始值和結束值,經過的時間一般被稱為持續時間。動畫執行時的曲線就是動畫函數。但是,在計算機中,不可能窮盡每一時刻的狀態,而是取多個采樣點,每個采樣點就叫做幀。要讓動畫流暢顯示,一般地需要每秒60幀
在SVG中實現動畫主要通過SMIL。SVG的動畫元素是和SMIL開發組合作開發的。SMIL開發組和SVG開發組合作開發了SMIL動畫規范,在規范中制定了一個基本的XML動畫特征集合。SVG吸收了SMIL動畫規范當中的動畫優點,並提供了一些SVG繼承實現
[注意]SVG動畫除了IE瀏覽器不支持之外,兼容其他主流瀏覽器
動畫元素
SVG動畫元素共有4個,包括:<set>、<animate>、<animateTransform>、<animateMotion>
【<set>】
<set>可以實現基本的延遲功能。就是指:可以在特定時間之后修改某個屬性值(也可以是CSS屬性值)
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <set attributeName="x" attributeType="XML" to="60" begin="2s" /> </text> </g> </svg>
2s后,文字會向右移動30px
【<animate>】
<animate>是基礎動畫元素,用於實現單屬性的動畫過渡效果
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate attributeName="x" to="60" begin="0s" dur="2s" repeatCount="indefinite" /> </text> </g> </svg>
【<animateTransform>】
<animateTransform>用於實現transform變換動畫效果
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animateTransform attributeName="transform" type="scale" from="1" to="1.5" begin="0s" dur="2s" repeatCount="indefinite" /> </text> </g> </svg>
【<animateMotion>】
<animateMotion>可以讓SVG各種圖形沿着特定的path路徑運動
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="0" x="0"> 火柴 <animateMotion path="M 20 20 H 60 V 50 Z" begin="0s" dur="3s" repeatCount="indefinite" /> </text> <path d="M 20 20 H 60 V 50 Z" fill="transparent" stroke="black"></path> </g> </svg>
動畫屬性
【attributeName】
attributeName表示要變化的元素屬性名稱
① 可以是元素直接暴露的屬性,例如,對應的text元素上的x, y或者font-size;
② 可以是CSS屬性。例如,透明度opacity
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate attributeName="opacity" to="0" begin="0s" dur="1s" repeatCount="indefinite" /> </text> </g> </svg>
【attributeType】
attributeType支持三個固定參數:CSS、XML、auto,用來表明attributeName屬性值的列表。x、y以及transform屬於XML;opacity等CSS屬於CSS;auto為默認值,自動判別的意思(實際上是先當成CSS處理,如果發現不認識,直接XML類別處理)。因此,如果不確信某屬性是XML類別還是CSS類別的時候,可以不設置attributeType值,直接讓瀏覽器自己去判斷
【from, to, by, values】
from 動畫的起始值
to 指定動畫的結束值
by 動畫的相對變化值
values 用分號分隔的一個或多個值,可以看成是動畫的多個關鍵值點
from、to、by、values相互之間有制約關系:
1、如果動畫的起始值與元素的默認值是一樣的,from參數可以省略
2、如果不考慮values,to、by兩個參數至少需要有一個出現。否則沒有動畫效果。to表示絕對值,by表示相對值。以位移距離為例子,如果from是100, to值為160,則表示移動到160這個位置;如果by值是160,則表示移動到100+160=260這個位置
3、如果to、by同時出現,則只識別to
4、 當values值設置並能識別時,from、to、by的值都會被忽略
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate attributeName="x" values="30;50;30;70;30" dur="2s" repeatCount="indefinite" /> </text> </g> </svg>
【時間表示】
SVG animation中的時間表示,常見單位有 "h"、"min"、"s"、"ms"。單位含義都是英文單位的縮寫。例如h表示小時(hour)
時間值支持小數寫法,因此,90s也可以使用1.5min表示。時間值還支持hh:mm:ss這種寫法,因此,90s也可以使用01:30表示
如果begin="1.5"沒有單位,這里的小數點表示秒,也就是1.5s的意思
【begin、end】
begin指動畫開始的時間,begin的定義是分號分隔的一組值。
例如,beigin="3s;6s"表示的是3s之后動畫走一下,6s時候動畫再走一下(如果之前動畫沒走完,會立即停止從頭開始)
所以,如果一次動畫時間為3s, 即dur="3s",同時沒有repeatCount屬性時候,可以看到動畫似乎連續執行了2次
begin的單值除了普通value,還有下面這些類別的value:
offset-value | syncbase-value | event-value | repeat-value | accessKey-value | media-marker-value | wallclock-sync-value | "indefinite"
① offset-value表示偏移值,數值前面有+或-,相對於document的begin值而言。
② syncbase-value基於同步確定的值。語法為:[元素的id].begin/end +/- 時間值。就是說借用其他元素的begin值進行加減運算,這個可以准確實現兩個獨立元素的動畫級聯效果
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate id="x" attributeName="x" to="70" dur="2" fill="freeze"/> <animate attributeName="y" begin="x.end" to="60" dur="2" fill="freeze"/> </text> </g> </svg>
③ event-value表示與事件相關聯的值。類似於PowerPoint動畫的“點擊執行該動畫”。語法是:[元素的id].[事件類型] +/- 時間值
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <circle id="circle1" cx="15" cy="15" r="15"/> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate id="x" attributeName="x" begin="circle1.click" to="70" dur="2"/> </text> </g> </svg>
點擊小球,會觸發文字的運動。如果想點擊小球2秒后文字才支持,加上偏移時間就可以了——begin="circle1.click+2s"
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <circle id="circle1" cx="15" cy="15" r="15"/> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate id="x" attributeName="x" begin="circle1.click" to="70" dur="2"/> </text> </g> </svg>
④ repeat-value指重復N次之后再進行其他運動。語法為:[元素的id].repeat(整數) +/- 時間值
[注意]經測試該屬性並不生效
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate id="x" attributeName="x" to="70" dur="2"/> <animate attributeName="y" begin="x.repeat(2)" to="70" dur="2" fill="freeze"/> </text> </g> </svg>
⑤accessKey-value定義快捷鍵。即按下某個按鍵動畫開始。語法為:accessKey("character")。character表示快捷鍵所在的字符
[注意]經測試該屬性並不生效
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="30"> 小火柴的藍色理想 <animate attributeName="y" begin="accessKey('s')" to="70" dur="2" /> </text> </g> </svg>
⑥ wallclock-sync-value指真實世界的時鍾時間定義。時間語法是基於在ISO8601中定義的語法
⑦ "indefinite"這個字符串值,表示“無限等待”。需要指向該動畫元素的超鏈接(SVG中的a元素)
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="40"> 小火柴的藍色理想 <animate id="animate1" attributeName="x" begin="indefinite" to="70" dur="1" repeatCount="indefinite"/> </text> <a xlink:href="#animate1"> <text y="30" fill="#cd0000" font-size="20">點擊</text> </a> </g> </svg>
【dur】
dur屬性值只有兩種:常規時間值 | "indefinite"
“常規時間值”就是3s之類的正常值;"indefinite"指動畫不執行
【calcMode, keyTimes, keySplines】
這幾個參數是控制動畫曲線的
calcMode屬性支持4個值:discrete | linear | paced | spline. 中文意思分別是:“離散”|“線性”|“踏步”|“樣條”
discrete from值直接跳到to值
linear animateMotion元素以外元素的calcMode默認值。動畫從頭到尾的速率都是一致的
paced 通過插值讓動畫的變化步調平穩均勻。僅支持線性數值區域內的值,這樣點之間“距離”的概念才能被計算(如position, width, height等)。如果”paced“指定,任何keyTimes或keySplines值都失效
spline 插值定義貝塞爾曲線。spline點的定義在keyTimes屬性中,每個時間間隔控制點由keySplines定義
keyTimes = “<list>”
跟上面提到的<list>類似,都是分號分隔一組值。keyTimes是關鍵時間點的意思,這里有一些約定的規則:首先,keyTimes值的數目要和values一致,如果是from/to/by動畫,keyTimes就必須有兩個值。然后對於linear和spline動畫,第一個數字要是0, 最后一個是1。 最后,每個連續的時間值必須比它前面的值大或者相等
paced模式下,keyTimes會被忽略;keyTimes定義錯誤,也會被忽略;dur為indefinite也會被忽略
keySplines = “<list>”
keySplines表示的是與keyTimes相關聯的一組貝塞爾控制點(默認0 0 1 1)。每個控制點使用4個浮點值表示:x1 y1 x2 y2. 只有模式是spline時候這個參數才有用,也是分號分隔,值范圍0~1,總是比keyTimes少一個值。
如果keySplines值不合法或個數不對,是沒有動畫效果的
下面是離散值discrete的例子
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="40"> 小火柴的藍色理想 <animate id="animate1" attributeName="x" dur="3" values="40;60;80;100" calcMode="discrete" repeatCount="indefinite"/> </text> </g> </svg>
下面是踏步值paces的例子
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="40"> 小火柴的藍色理想 <animate id="animate1" attributeName="x" dur="3" values="40;60;80;100" calcMode="paced" repeatCount="indefinite"/> </text> </g> </svg>
下面是貝塞爾曲線spline的例子
<svg height="70" xmlns="http://www.w3.org/2000/svg"> <g> <text font-family="microsoft yahei" font-size="20" y="30" x="40"> 小火柴的藍色理想 <animate id="animate1" attributeName="x" dur="3" values="40;60;100" keyTimes="0; .8; 1" calcMode="spline" keySplines=".5 0 .5 1; 0 0 1 1" repeatCount="indefinite"/> </text> </g> </svg>
【repeatCount, repeatDur】
repeatCount表示動畫執行次數,可以是合法數值或者"indefinite"
repeatDur定義重復動畫的總時間。可以是普通時間值或者"indefinite"
<animate attributeName="x" to="60" dur="3s" repeatCount="indefinite" repeatDur="10s" />
上面的代碼中,動畫只執行完整3個 + 一個1/3個動畫。因為repeat總時間是10s
【fill】
fill表示動畫間隙的填充方式。支持參數有:freeze | remove。其中remove是默認值,表示動畫結束直接回到開始的地方。freeze“凍結”表示動畫結束后像是被凍住了,元素保持了動畫結束之后的狀態
【accumulate, additive】
accumulate是累積的意思。支持參數有:none | sum。默認值是none,如果值是sum表示動畫結束時候的位置作為下次動畫的起始位置
additive控制動畫是否附加。支持參數有:replace | sum。默認值是replace.,如果值是sum表示動畫會附加到其他低優先級的動畫上
【restart】
restart支持的參數有:always | whenNotActive | never.
always是默認值,表示總是。whenNotActive表示動畫正在進行的時候,是不能重啟動畫的。never表示動畫是一波流
【min、max】
min/max表示動畫執行最短和最長時間。支持參數為時間值和"media"(媒介元素有效), max還支持indefinite
API
SVG animation有內置的API可以暫停和啟動動畫的。語法為:
// 暫停
svg.pauseAnimations();
// 恢復
svg.unpauseAnimations()
<svg height="70" xmlns="http://www.w3.org/2000/svg" id="svg"> <g id="test"> <text font-family="microsoft yahei" font-size="20" y="30" x="40"> 小火柴的藍色理想 <animate id="animate1" attributeName="x" dur="2" to="80" repeatCount="indefinite" /> </text> </g> </svg> <script> svg.onclick = function(){ if(!this.paused){ this.paused = true; this.pauseAnimations(); }else{ this.paused = false; this.unpauseAnimations(); } } </script>
點擊文字可暫停或恢復
