目錄[^1]
一、SVG SMIL Animation概覽
1.1 SMIL是什么?
全稱Synchronized Multimedia Integration Language
SMIL允許你做這些事情:
- 動(dòng)畫元素的數(shù)值屬性(X,Y,...)
- 動(dòng)畫屬性變換(平移或旋轉(zhuǎn)或縮放)
- 動(dòng)畫顏色變換
- 沿著指定路徑運(yùn)動(dòng) CSS3不能做到
1.2 SMIL強(qiáng)大之處
SMIL的強(qiáng)大之處在于:不需要CSS,不需要JS,只需要 animate 元素即可。實(shí)例:
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="200" y="200" width="60" height="60" fill="red"></rect>
<animateTransform attributeName="transform" begin="0s" dur="10s" type="rotate" from="0 160 160" to="360 160 160" repeatCount="indefinite"/>
</svg>

二、SMIL Animation元素及效果概覽
- <set>
- <animate>
- <animateColor>
- <animateTransform>
- <animateMotion>
2.1 <set />
<set>意思是設(shè)置,此元素沒(méi)有動(dòng)畫效果。但是可以實(shí)現(xiàn)基本的延遲功能。也就是說(shuō),可以在特定時(shí)間之后修改某個(gè)屬性值(也可以是CSS屬性值)。
實(shí)例:矩形會(huì)在3s后從x="160" 移動(dòng)到x="60"的位置。
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
<rect x="200" y="200" width="60" height="60" fill="red">
<set attributeName="x" attributeType="XML" to="60" begin="3s" />
</rect>
</svg>
2.2 <animate />
基礎(chǔ)動(dòng)畫元素。實(shí)現(xiàn)單屬性的動(dòng)畫過(guò)渡效果。實(shí)例:矩形沿著X軸平移
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
<rect x="200" y="200" width="60" height="60" fill="red">
<animate attributeName="x" from="200" to="10" begin="0s" dur="1s" repeatCount="indefinite" />
</rect>
</svg>
2.3 <animateColor />
顏色動(dòng)畫,其可以實(shí)現(xiàn)的功能與效果,animate也可以做到,因此,該屬性已經(jīng)被廢棄
2.4 <animateTransform></animateTransform>
實(shí)現(xiàn) transform 變換動(dòng)畫效果。實(shí)例,矩形快速變大:
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
<rect x="200" y="200" width="60" height="60" fill="red"></rect>
<animateTransform attributeName="transform" begin="0s" dur="3s" type="scale" from="1" to="3"></animateTransform>
</svg>
2.5 <animateMotion>
animateMotion元素可以讓SVG各種圖形沿著特定的 path 路徑運(yùn)動(dòng)。實(shí)例:矩形按照既定路徑運(yùn)動(dòng)
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="-400 -400 800 800">
<rect x="-25" y="-25" width="50" height="50" fill="rgba(0,255,255,.6)">
<animateMotion path="M 0 0 L 100 100 A 200 200 0 1 0 0 -100" dur="3s" rotate="auto" fill="freeze"></animateMotion>
</rect>
<path id="motion-path" d="M 0 0 L 100 100 A 200 200 0 1 0 0 -100" fill="none" stroke="gray"></path>
</svg>
2.6 自由組合
讓矩形沿著路徑來(lái)回移動(dòng),并更改顏色
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="-400 -400 800 800">
<circle cx="0" cy="0" r="5" fill="red"></circle>
<circle cx="0" cy="-100" r="5" fill="yellow"></circle>
<rect x="-25" y="-25" rx="5" ry="5" width="50" height="50" fill="red">
<animateMotion id="clockwise" path="M 0 0 L 100 100 A 200 200 0 1 0 0 -100" dur="3s" rotate="auto" begin="0; counterclockwise.end + 1s" fill="freeze"></animateMotion>
<animateMotion id="counterclockwise" path="M 0 -100 A 200 200 0 1 1 100 100 L 0 0" dur="3s" begin="clockwise.end + 1s" rotate="auto" fill="freeze"></animateMotion>
<animate id="toYellow" attributeType="XML" attributeName="fill"
begin="0; toRed.end + 1s"
from="red" to="yellow" dur="3s" fill="freeze"></animate>
<animate id="toRed" attributeType="XML" attributeName="fill"
begin="toYellow.end + 1s"
from="yellow" to="red" dur="3s" fill="freeze"></animate>
</rect>
<path id="motion-path" d="M 0 0 L 100 100 A 200 200 0 1 0 0 -100" fill="none" stroke="gray"></path>
</svg>
三、SVG Animation參數(shù)詳解
3.1 attributeName = <attributeName>
需要變化的元素屬性名稱:
- 可以是元素直接暴露的屬性,例如,對(duì)于反復(fù)出現(xiàn)的矩形對(duì)應(yīng)的
<rect>元素上的x,y或者rx,ry - 還可以是CSS屬性。例如,透明度
opacity。
3.2 attributeType = "CSS | XML | auto"
attributeType支持三個(gè)固定參數(shù),CSS、XML、auto,用來(lái)表示attributeType屬性值的列表。x,y以及transform就屬于XML;opacity就屬于CSS;auto為默認(rèn)值,自動(dòng)判別的意思,實(shí)際上縣當(dāng)成CSS處理,如果發(fā)現(xiàn)不認(rèn)識(shí),直接X(jué)ML類別處理。因此如果不確定某屬性是XML還是CSS類別的時(shí)候設(shè)置為auto。雖然如此,為了瀏覽器性能最佳,還是盡量區(qū)分類別。
3.3 from,to,by,values
上面的4個(gè)屬性是一個(gè)家族的,他們解決的問(wèn)題是,從哪里來(lái)?到哪里去?怎么去?去干什么?
- from = "value" :動(dòng)畫的起始值。
- to = "value" :指定動(dòng)畫的結(jié)束值。
- by = "value" :動(dòng)畫的相對(duì)變化值。
- values = "list" :用分號(hào)分隔的一個(gè)或多個(gè)值,可以看出是動(dòng)畫的多個(gè)關(guān)鍵值點(diǎn)。
from,to,by,values雖然是一個(gè)家族的,但是相互之間還是有制約關(guān)系的:
如果動(dòng)畫的起始值與元素的默認(rèn)值是一樣的,
form參數(shù)可以省略。(不考慮values)to、by兩個(gè)參數(shù)至少需要有一個(gè)出現(xiàn),否則沒(méi)有動(dòng)畫效果。to表示絕對(duì)值,by表示相對(duì)值。
拿位移舉例,如果from="100",to="160"則表示移動(dòng)到160這個(gè)位置,但是by="160"表示100+160=260,表示移動(dòng)到260的位置。如果
to,by同時(shí)出現(xiàn),則by打醬油,只是別to。如果to,by,values都沒(méi)設(shè)置,自然沒(méi)動(dòng)畫效果。如果任意(包括from)一個(gè)屬性的值不合法,嚴(yán)格來(lái)說(shuō)是沒(méi)有動(dòng)畫效果的。但是Chrome有容錯(cuò)機(jī)制,可能會(huì)出現(xiàn)動(dòng)畫。
values可以是一個(gè)或多個(gè)值。當(dāng)
values的值設(shè)置并被識(shí)別時(shí),from,to,by的值都會(huì)被忽略。
values的功能就是實(shí)現(xiàn)多點(diǎn)之間動(dòng)畫。而from,to,by只能實(shí)現(xiàn)兩個(gè)點(diǎn)的切換。實(shí)例,矩形來(lái)回移動(dòng):
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="-400 -400 800 800">
<rect x="-25" y="-25" rx="5" ry="5" width="50" height="50" fill="red">
<animate attributeName="fill" values="red;green;blue;black" dur="4s" fill="freeze" />
<animate attributeName="x" values="0;300;100;500" dur="4s" fill="freeze"/>
</rect>
</svg>
總結(jié)為五個(gè)動(dòng)畫:from-to動(dòng)畫、from-by動(dòng)畫、to動(dòng)畫、by動(dòng)畫、values動(dòng)畫。
3.4 begin,end
begin指動(dòng)畫開(kāi)始的時(shí)間,看上去很簡(jiǎn)單。例如begin="3s"只是最基本的表示方式。
begin的定義是分號(hào)分隔的一組值。例如begin="3s;5s"表示的是3s之后動(dòng)畫走一下,5s的時(shí)候再走一下(如果之前的動(dòng)畫沒(méi)走完,會(huì)立即停止并從頭開(kāi)始)
SVG Animate中的時(shí)間表示
常見(jiàn)單位有"h" | "min" | "s" | "ms",以上單位都是英文單位的縮寫。
時(shí)間值支持小數(shù)寫法,因此90s也可以用1.5min表示。時(shí)間值還支持hh:mm:ss這種寫法,因此,90s我們也可以使用01:30表示。
還有一點(diǎn),十進(jìn)制的小數(shù)值是秒的浮點(diǎn)定義,什么意思呢?例如 begin="1.5" 沒(méi)有單位,這里的小數(shù)點(diǎn)表示秒,也就是 1.5s的意思。所以上面N次出現(xiàn)的begin=3s 也可以簡(jiǎn)寫作 begin="3"。
begin的單值除了普通的value還有下面這些類別的value:
offset-value 表示偏移值,數(shù)值前面有+ 或 - ,指相對(duì)于document的begin值;
syncbase-value 基于同步確定的值。語(yǔ)法為:[ID].begin/end +/- 時(shí)間值。
例如: 2.6綜合實(shí)例的begin="0; counterclockwise.end + 1s"意思是上一個(gè)動(dòng)畫結(jié)束1s之后。event-value 這個(gè)表示與時(shí)間相關(guān)聯(lián)的值。類似于 ”點(diǎn)擊執(zhí)行該動(dòng)畫“, 語(yǔ)法為:
id.event +- time
例如:begin = "circle.click + 2s"表示點(diǎn)擊2s之后執(zhí)行動(dòng)畫
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="-400 -400 800 800">
<circle id="circle" cx="100" cy="100" r="20"></circle>
<rect x="-25" y="-25" rx="5" ry="5" width="100" height="100" fill="red">
<animate attributeName="x" to="260" begin="circle.click + 2s" dur="2s" />
</rect>
</svg>
需要注意的是,這類與實(shí)踐關(guān)聯(lián)的SVG需要內(nèi)聯(lián)在頁(yè)面中,否則click什么的都是徒勞。
-
repeat-value 指重復(fù)多少次之后做什么。語(yǔ)法為:[ID].repeat(整數(shù)) +/- 時(shí)間值。
實(shí)例:矩形水平移動(dòng)兩次之后,斜向運(yùn)動(dòng)
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="100" width="100" height="100" fill="#ff5050">
<animate id="x" attributeName="x" to="800" begin="0s" dur="3s" repeatCount="indefinite" />
<animate attributeName="y" to="800" begin="x.repeat(2)" dur="3s" fill="freeze" />
</rect>
</svg>
begin="x.repeat(2)"指id為x的元素的動(dòng)畫重復(fù)2次之后執(zhí)行該動(dòng)畫。
-
accessKey-value 定義快捷鍵。即按下某個(gè)按鍵動(dòng)畫開(kāi)始。語(yǔ)法為:
accessKey("character").character表示快捷鍵所在字符。
實(shí)例:按下A鍵動(dòng)畫執(zhí)行(firefox上可用,chrome不支持)
<svg xmlns="http://www.w3.org/2000/svg">
<rect x="100" y="100" width="100" height="100" fill="#ff5050">
<animate attributeName="x" to="400" begin="accessKey(a)" dur="3s" repeatCount="indefinite" />
</rect>
</svg>
wallclock-sync-value 指真實(shí)世界的時(shí)鐘定義,時(shí)間語(yǔ)法是基于ISO8601中定義的語(yǔ)法,例如:2018-01-23T10:40:54.45+01:00
indefinite 就是這個(gè)字符串值,表示無(wú)限等待,需要
beginElement()方法觸,或者指向該動(dòng)畫元素的超鏈接(SVG中的a元素)觸發(fā)。
beginElement()觸發(fā)實(shí)例:
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="600" height="200">
<rect x="100" y="100" width="100" height="100">
<animate attributeName="x" to="400" begin="indefinite" dur="2s">
</rect>
</svg>
<script type="text/javascript">
var animate = document.getElementsByTagName("animate")[0];
if (animate){
document.getElementById("svg").onclick = function(){
animate.beginElement();
}
}
</script>
超鏈接(a標(biāo)簽)觸發(fā)實(shí)例:
<svg id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="200">
<rect x="100" y="100" width="100" height="100">
<animate id="animate" attributeName="x" to="400" begin="indefinite" dur="2s"/>
</rect>
<a xlink:href="#animate">
<text x="100" y="60" fill="#cd0000" font-size="30">點(diǎn)擊</text>
</a>
</svg>
end與begin的屬性大同小異,無(wú)需重復(fù)說(shuō)明。
3.5 dur
dur有兩種值:常規(guī)時(shí)間值 | “indefinite”
常規(guī)時(shí)間值就是(3s)這種正常值;indefinite指時(shí)間無(wú)限。
動(dòng)畫時(shí)間無(wú)限,實(shí)際上就是動(dòng)畫不執(zhí)行,因此設(shè)置“indefinite”跟沒(méi)有設(shè)置dur值一個(gè)意思,與dur解析異常一個(gè)意思。
3.6 calcMode, keyTimes, keySplines
這幾個(gè)參數(shù)是控制動(dòng)畫節(jié)奏,先快后慢還是先慢后快。
- calcMode屬性支持4個(gè)值:discrete 、linear、paced、spline中文意思是:離散,線性、踏步、樣條
- discrete : from值直接跳轉(zhuǎn)到to的值
- linear:animateMotion元素以外元素的calcMode默認(rèn)值動(dòng)畫從頭到尾速率一致。
- paced:通過(guò)插值讓動(dòng)畫的變化步調(diào)平穩(wěn)均勻。僅支持線性數(shù)值區(qū)域內(nèi)的值,這樣點(diǎn)之間“距離”的概念才能被計(jì)算(如position、width、height)。如果“paced”被指定,任何“keyTimes”或“keySplines”的值都將無(wú)效。
- spline插值定義貝塞爾曲線。spline點(diǎn)定義在keyTimes屬性中,每個(gè)時(shí)間間隔控制點(diǎn)由keySplines定義。
keyTimes = "<list>"
跟上面提到的<list>類似,都是分好分隔一組值。keyTimes意思是關(guān)鍵時(shí)間點(diǎn)。前面提到過(guò)values也是多個(gè)值,這里有一些約定的規(guī)則:首先keyTimes值得數(shù)目要和values一致,如果是from、to、by動(dòng)畫,keyTimes就必須有兩個(gè)值。
然后對(duì)于linear和spline動(dòng)畫,第一個(gè)數(shù)值要是0,最后一個(gè)是1。最后每個(gè)連續(xù)的時(shí)間值必須比它前面的值大或者相等。
paced模式下,keyTimes會(huì)被忽略;
keyTimes定義錯(cuò)誤,也會(huì)被忽略;
dur為indefinite也會(huì)被忽略。keySplines="<list>"
keySplines表示的是與keyTimes相關(guān)聯(lián)的一組貝塞爾控制點(diǎn)(默認(rèn)0 0 1 1)。每個(gè)控制點(diǎn)使用4個(gè)浮點(diǎn)值表示:x1 y1 x2 y2,只有模式是spline的時(shí)候這個(gè)參數(shù)才有用,也是分號(hào)分隔,值范圍0~1,總比keyTimes少一個(gè)值。
如果keySplines值不合法或個(gè)數(shù)不對(duì),是沒(méi)有動(dòng)畫效果的。
來(lái)看一個(gè)綜合實(shí)例:演示效果
<svg width="320" height="100" xmlns="http://www.w3.org/2000/svg">
<text font-size="60" y="60" x="160">馬
<animate attributeName="x" dur="5s" values="0; 20; 160" calcMode="linear" />
</text>
</svg>
<svg width="320" height="100" xmlns="http://www.w3.org/2000/svg">
<text font-size="60" y="60" x="160">馬
<animate attributeName="x" dur="5s" values="0; 80; 160" calcMode="paced"/>
</text>
</svg>
<svg width="320" height="100" xmlns="http://www.w3.org/2000/svg">
<text font-size="60" y="60" x="160">馬
<animate attributeName="x" dur="5s" values="0; 80; 160" keyTimes="0; .8; 1" calcMode="linear"/>
</text>
</svg>
<svg width="320" height="100" xmlns="http://www.w3.org/2000/svg">
<text font-size="60" y="60" x="160">馬
<animate attributeName="x" dur="5s" values="0; 80; 160" keyTimes="0; .8; 1" calcMode="spline" keySplines=".5 0 .5 1; 0 0 1 1" />
</text>
</svg>
values確定動(dòng)畫的關(guān)鍵位置,keyTimes確定到這個(gè)關(guān)鍵點(diǎn)需要的時(shí)間,keySplines確定的是每個(gè)時(shí)間之間的貝塞爾曲線,也就是具體緩動(dòng)表現(xiàn)。
CSS3寫的transition動(dòng)畫效果,也是這么回事,只是values值就兩個(gè),所以,keyTimes只能是0;1,貝塞爾曲線就一個(gè),要不ease,要不liner。
keySplines=".5 0 .5 1; 0 0 1 1"這里的動(dòng)畫曲線可以自由調(diào)節(jié),可以參考以下曲線:

3.7 repeatCount,repeatDur
repeatCount 表示動(dòng)畫執(zhí)行次數(shù),可以是合法數(shù)值或者"indefinite"(動(dòng)畫循環(huán)到電腦死機(jī))。
repeatDur 定義重復(fù)動(dòng)畫的總時(shí)間??梢允瞧胀〞r(shí)間值或者"indefinite"(動(dòng)畫循環(huán)到電腦死機(jī))。
<animate attributeName="x" to="60" dur="3s" repeatCount="indefinite" repeatDur="10s" />
動(dòng)畫執(zhí)行 3 + 1/3 次。因?yàn)閞epeatDur=“10s”
3.8 fill
fill表示動(dòng)畫間隙的填充方式。支持參數(shù)有:freeze | remove,其中remove是默認(rèn)值,表示動(dòng)畫結(jié)束直接回到開(kāi)始的地方,freeze表示動(dòng)畫結(jié)束凍住,表示保持動(dòng)畫結(jié)束的信息。
3.9 accumulate,additive
accumulate 是累積的意思。支持參數(shù)有none | sum 。默認(rèn)值是none,值sum表示動(dòng)畫結(jié)束時(shí)的位置作為下次動(dòng)畫的起始位置。
additive 控制動(dòng)畫是否附加。支持參數(shù)有:replace | sum。默認(rèn)值replace,值sum表示動(dòng)畫的基礎(chǔ)指示會(huì)附加到其他低優(yōu)先級(jí)的動(dòng)畫上。
實(shí)例1,
<animateMotion begin="0" dur="5s" path="[some path]" additive="sum" fill="freeze" />
<animateMotion begin="5s" dur="5s" path="[some path]" additive="sum" fill="freeze" />
<animateMotion begin="10s" dur="5s" path="[some path]" additive="sum" fill="freeze" />
輪到第二個(gè)動(dòng)畫的時(shí)候,路徑從第一個(gè)動(dòng)畫路徑結(jié)束的地方開(kāi)始,三個(gè)動(dòng)畫完美結(jié)合
實(shí)例2:在線查看效果
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500">
<rect x="200" y="200" width="20" height="20"></rect>
<animateTransform attributeName="transform" type="scale" from="1" to="4" dur="5s" additive="sum" fill="freeze"/>
<animateTransform attributeName="transform" type="rotate" from="0 10 10" to="360 10 10" dur="5s" fill="freeze" additive="sum"/>;
</svg>
3.10 restart
restart這個(gè)屬性誕生的背景如下:很多動(dòng)畫其觸發(fā)可能與事件相關(guān),例如,點(diǎn)擊圓圈,矩形就跑。而且,似乎每點(diǎn)一次,矩形就動(dòng)一下。現(xiàn)在,存在這種情況,希望矩形只動(dòng)一次,之后點(diǎn)擊就不動(dòng)了。這種需求迫使restart參數(shù)的出現(xiàn)。
支持的參數(shù)有:** always | whenNotActive | never**
always 是默認(rèn)值,表示總是,也就是點(diǎn)一次圈圈,馬兒跑一下。
whenNotActive 表示動(dòng)畫正在執(zhí)行的時(shí)候,不能重啟動(dòng)畫。
never 表示執(zhí)行一次就不再執(zhí)行。
3.11 min,max
min/max表示動(dòng)畫執(zhí)行最短和最長(zhǎng)時(shí)間。支持參數(shù)為時(shí)間值和"media"(沒(méi)接元素有效),max還支持indefinite。
四、動(dòng)畫暫停與播放
SVG Animation中是有內(nèi)置的API可以暫停和啟動(dòng)動(dòng)畫,語(yǔ)法:
//暫停
svg.pauseAnimations();
//播放
svg.unpauseAnimation();
通過(guò)ID獲取SVG元素
var svgElement = document.getElementById("rect1")
五、animeJS動(dòng)畫庫(kù)
http://animejs.com/
SVG和animeJS搭配使用可以做出非常流暢的動(dòng)畫。
可以查看我的
實(shí)例1:http://jsbin.com/faxikem/5/edit?html,output
實(shí)例2:https://github.com/PowerXuan/MonstarLogoSVGAnimation