SVG之Animation

<animate>元素用於實現動畫效果(動畫截圖比較麻煩,本文中的例子最好直接寫demo看效果)css

基本動畫

將<animate>元素嵌入到元素內,來實現該元素的動畫效果。svg

<rect x="10" y="10" width="200" height="20" stroke="black" fill="none">
    <animate
    attributeName="width"
    attributeType="XML"
    from="200" to="20"
    begin="0s" dur="5s"
    fill="freeze" />
</rect>

以上代碼會一個200*20的長方形,在5秒內漸變成一個20*20的正方形,而且在動畫結束時停留在正方形的狀態。動畫

<animate>元素的基本屬性:spa

  • attributeName

定義發生變化的元素屬性名code

  • attributeType

當attributeType="XML"時,attributeName被認爲是XML的屬性;當attributeType="CSS"時,attributeName被認爲是css的屬性;不指定attributeType時,默認爲"auto",會先將attributeName做爲css的屬性,若是無效,再將attributeName做爲XML的屬性。orm

  • from & to & by

from和to分別定義發生變化的屬性的初始值和終止值。from可缺省,表示初始值即爲<animate>父元素相應的屬性值。可用by替換to,表示變化偏移量。能夠理解爲to = from + by。對象

  • begin & dur & end

begin定義動畫開始時間;dur定義動畫所需時間;end定義動畫終止時間。時間單位h:小時;min:分鐘;s:秒;ms:毫秒。默認時間單位爲sblog

  • fill

當fill="freeze"時,動畫終止時,發生變化的元素屬性值停留在動畫終止時的狀態;當fill="remove"時,動畫終止時,發生變化的元素屬性值回覆到動畫起始時的狀態。fill屬性默認值爲remove。
容許在同一個元素內嵌入多個<animate>事件

<rect x="10" y="10" width="20" height="20" style="stroke: black; fill: #cfc;">
    <animate attributeName="width" attributeType="XML" begin="0s" dur="2s" from="20" to="120" fill="freeze"/>
    <animate attributeName="height" attributeType="XML" begin="0s" dur="2s" from="20" by="100" fill="freeze"/>
</rect>

動畫時間

當begin設置爲一個具體時間,好比2s,svg會在元素加載完畢後,過2秒開始執行動畫。
begin還能夠指定一個其餘<animate>的begin或者end,好比:ip

<circle cx="60" cy="60" r="30" style="fill: #f9f; stroke: gray;">
    <animate id="c1" attributeName="r" attributeType="XML" begin="0s" dur="4s" from="30"  to="10" fill="freeze"/>
</circle>
<circle cx="120" cy="60" r="10" style="fill: #9f9; stroke: gray;">
    <animate attributeName="r" attributeType="XML" begin="c1.end" dur="4s" from="10" to="30" fill="freeze"/>
</circle>

第二個圓的動畫執行起始時間爲第一個圓動畫執行完畢時間。
begin屬性還能夠進行簡單計算:
begin="c1.end+1.5s":表示動畫執行起始時間爲第一個圓執行完畢後的1.5秒。

當end設置爲一個具體時間,好比2s,svg會在元素加載完畢後,過2秒即中止執行動畫,無論這個元素的動畫是否執行完畢。若是end設置的比begin小,則動畫根本不會執行。

end一樣能夠指定一個其餘<animate>的begin或者end,一樣支持計算。

重複動畫

經過設置repeatDur或者repeatCount屬性,讓動畫重複執行。

  • repeatDur

設置動畫執行的總時長。在repeatDur設置的時間內,動畫一直會重複執行。若是repeatDur小於dur,repeatDur的做用與end同樣。

  • repeatCount

設置動畫重複執行的次數。
repeatDur和repeatCount均可以經過設置爲indefinit實現無限循環動畫。
當repeatDur和repeatCount同時做用於同一個<animate>時,動畫終止時間取二者中較小值。
repeat可做爲begin和end中的參數使用:

<circle cx="60" cy="60" r="15" style="fill: none; stroke: red;">
    <animate id="circleAnim" attributeName="cx" attributeType="XML" begin="0s" dur="5s" repeatCount="3" from="60" to="260" fill="freeze"/>
</circle>
<rect x="230" y="80" width="30" height="30" style="fill: #ccf; stroke: black;">
    <animate attributeName="x" attributeType="XML" begin="circleAnim.repeat(1)+2.5s" dur="5s" from="230" to="30" fill="freeze"/>
</rect>

長方形的動畫會在圓形動畫執行過一遍後延遲2.5秒後開始執行。
repeat(n)中的n需大於0。

複雜屬性的動畫

動畫還可做用於顏色、paths、d等非純數字屬性。

顏色的動畫過程能夠分解成r,g,b,a四個數字的漸變。好比從#f00變化到#0f0,紅色部分從1漸變到0,綠色部分同時從0漸變到1。
paths和d要實現動畫有一個前提,其參數個數不能變。變化先後參數一一對應,全部參數同時漸變。

<polygon points="30 30 70 30 90 70 10 70" style="fill:#fcc; stroke:black">
    <animate id="animation"
             attributeName="points"
             attributeType="XML"
             to="50 30 70 50 50 90 30 50"
             begin="0s" dur="5s" fill="freeze"/>
</polygon>
<path d="M15 50 Q 40 15, 50 50, 65 32, 100 40" style="fill:none; stroke: black" transform="translate(0,50)">
    <animate attributeName="d"
             attributeType="XML"
             to="M50 15 Q 15 40, 50 50, 32 65, 40 100"
             begin="0s" dur="5s" fill="freeze"/>
</path>

多節點動畫

實現一個屬性的連續變化有兩種方式:

  1. 多個<animate>組合
  2. 使用value + keyTimes + calcMode屬性

基礎動畫中提到過多<animate>組合方式;這裏說下values + keyTimes + calcMode。

  • values

values屬性值表示一個動畫通過的節點數值,數值間以分號分割。

<circle cx="175" cy="75" r="20" fill="red">
    <animate attributeName="r"
             attributeType="XML"
             values="20;50;20"
             begin="0" dur="1" repeatCount="indefinite"
             fill="freeze"></animate>
</circle>

上例中1秒內,圓的半徑由20變爲50,再由50變爲20。

  • keyTimes

keyTimes屬性值與values屬性值一一對應,第一個數值永遠是0(表示起始時間點),最後一個數值永遠是1(表示終止時間點),中間的數值表示變化到對應values屬性值時所處時間點百分比(0~1之間)。

<circle cx="175" cy="75" r="20" fill="red">
    <animate attributeName="r"
             attributeType="XML"
             values="20;50;20"
             keyTimes="0;0.2;1"
             begin="0" dur="1" repeatCount="indefinite"
             fill="freeze"></animate>
</circle>

上例中0.2秒時圓的半徑由20變爲50,在以後的0.8秒又從50變爲20。

  • calcMode

calcMode能夠影響動畫各階段的表現。calcMode有四種屬性值:paced, linear, discrete, spline

calcMode="paced"時,動畫會忽略keyTimes屬性,根據values數值以勻速變化。
calcMode="linear"時,動畫根據values和keyTimes屬性,在每一個時間段內勻速變化。linear爲calcMode的默認屬性值。
calcMode="discrete"時,動畫根據values和keyTimes屬性,去掉過分動畫,到了keyTimes的某個節點,屬性值直接變爲values對應數值。
calcMode="spline"時,須要配合keySplines屬性,設置每一個時間段內的三次貝塞爾變化曲線。

<circle cx="175" cy="75" r="20" fill="red">
    <animate attributeName="r"
             attributeType="XML"
             values="20;50;20"
             keyTimes="0;.15;1"
             calcMode="spline"  keySplines=".5 0 .5 1;.5 0 .5 1"
             begin="0" dur="1" repeatCount="indefinite"
             fill="freeze"></animate>
</circle>

上例中加上貝塞爾曲線後圓形的變化有點相似心跳的節奏。

<set>

<set>元素也可設置屬性變化的動畫,但與<animate>有明顯區別:

  • 不須要from屬性,起始狀態即爲父節點屬性值。
  • 一到begin屬性設置的時點,指定的attributeName屬性值即改成to指定的屬性值,沒有過分動畫。
  • attributeName能夠是屬性值非數字的屬性,如style="visibility: hidden;"
<text text-anchor="middle" x="60" y="60" style="visibility: hidden;">
    <set attributeName="visibility" attributeType="CSS"
         to="visible" begin="1s" dur="10s" fill="freeze"></set>
    <set attributeName="x" attributeType="XML"
         to="120" begin="2s" dur="10s" fill="freeze"></set>
    All gone!
</text>

上例中1秒後顯示All gone!,再過1秒後文字移動至(120,60)。

<animateTransform>

要實現transform屬性改變的動畫,須要使用<animateTransform>來替代<animate>。

<rect x="-10" y="-10" width="20" height="20" style="fill: #ff9; stroke: black;">
    <animateTransform id="a1" attributeName="transform" attributeType="XML" type="scale" from="1" to="4 2" additive="sum" begin="0s" dur="4s" fill="freeze"></animateTransform>
    <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="45" additive="sum" begin="a1.end" dur="4s" fill="freeze"></animateTransform>
</rect>

<animateTransform>的attributeName指定爲transform(我的感受有點多餘,animateTransform自己就是應用於改變transform屬性值的)。用type屬性指定transform須要改變的屬性(translate, scale, rotate, skewX, skewY)。

<animateTransform>還有個additive屬性。上例中兩個<animateTransform>同時做用於一個<rect>元素,默認狀況下additive屬性值爲replace,表示當前<animateTransform>的初始狀態與以前的<animateTransform>變化結果無關。若是additive="sum",表示當前<animateTransform>的變化基於以前的<animateTransform>變化之上。

上例結果:

clipboard.png
clipboard.png

(剛看到一個長方形使用rotate會變成一個菱形感受哪裏不對,再回想了一下translate的本質和形變的次序,就明瞭了)

<animateMotion>

<animateMotion>是個很強大的元素,以前全部動畫功能在css裏均可以用animation實現,但<animateMotion>能實現的功能是單憑css沒法實現的。
<animateMotion>可讓父元素沿着指定的路徑運動!
直線路徑能夠簡單使用from + to屬性來指定起點和終點:

<g>
    <rect x="0" y="0" width="50" height="30" style="fill: #ccc;"/>
    <circle cx="40" cy="30" r="10" style="fill: #cfc; stroke: green;"/>
    <circle cx="10" cy="30" r="10" style="fill: #cfc; stroke: green;"/>
    <animateMotion from="0,0" to="60,30" dur="4s" fill="freeze"/>
</g>

也能夠實用path指定複雜的路徑

<g>
    <rect x="0" y="0" width="50" height="30" style="fill: #ccc;"/>
    <circle cx="40" cy="30" r="10" style="fill: #cfc; stroke: green;"/>
    <circle cx="10" cy="30" r="10" style="fill: #cfc; stroke: green;"/>
    <animateMotion path="M50,125 C 100,25 150,225, 200, 125" dur="4s" fill="freeze"/>
</g>

也能夠指定<path>元素做爲本身的路徑

<path id="cubicCurve" d="M50,125 C 100,25 150,225, 200, 125"/>
<g>
    <rect x="0" y="0" width="50" height="30" style="fill: #ccc;"/>
    <circle cx="40" cy="30" r="10" style="fill: #cfc; stroke: green;"/>
    <circle cx="10" cy="30" r="10" style="fill: #cfc; stroke: green;"/>
    <animateMotion dur="6s" fill="freeze">
        <mpath xlink:href="#cubicCurve"/>
    </animateMotion>
</g>

<animateMotion>有個rotate屬性,默認爲0,元素在運動時不會旋轉。當設置爲auto時,元素對應的水平軸會始終與path路徑保持水平,上圖中加上rotate="auto"後的效果就像是車子開過山坡。

<animateMotion>節點

與多節點動畫相似,<animateMotion>也有三個屬性用於控制動畫的節點。

  • keyPoints

第一個屬性值爲0(表示path路徑的起始位置),最後一個屬性值爲1(表示path路徑的終點位置),各屬性值用分號分割,每一個屬性值與keyTimes的屬性值一一對應,表示到某個時點運動到相對於路徑的哪一個位置。

  • keyTimes

第一個屬性值爲0(表示動畫起始時間),最後一個屬性值爲1(表示動畫終止時間),各屬性值用分號分割,每一個屬性值與keyPoints的屬性值一一對應,表示運動到某個位置須要的總動畫時常佔比。

  • calcMode

與多節點動畫中的calcMode屬性值及做用徹底一致。

<path d="M-10,-3 L10,-3 L0,-25z" style="fill: yellow; stroke: red;" >
    <animateMotion
    path="M50,125 C 100,25 150,225, 200, 125"
    rotate="auto"
    keyPoints="0;0.2;0.8;1"
    keyTimes="0;0.33;0.66;1"
    calcMode="linear"
    dur="6s" fill="freeze"/>
</path>

CSS動畫

css中有兩種實現動畫的方式:transition和animation。
transition用於實現較簡單的兩點動畫,即根據屬性的起始狀態和終止狀態,完整中間過渡動畫。

transition

transition動畫相關的css屬性以下

  • transition-property

定義動畫屬性,可定義多個屬性,逗號分隔

  • transition-duration

定義動畫執行時間,單位(s,ms),可定義多個屬性,與transition-property一一對應,逗號分隔

  • transition-timing-function

與calcMode相似,影響動畫的表現。默認值爲ease。可選項有:ease | linear | ease-in | ease-out | ease-in-out | step-start | step-end | steps(<integer>[, [ start | end ] ]?) | cubic-bezier(<number>, <number>, <number>, <number>)

  • transition-delay

定義動畫延遲多少時間後開始執行

其中transition-timing-function中的step-start、step-end和steps有點相似calcMode中的discrete模式,狀態之間切換沒有中間過渡。具體來講stepts(<integer>[, [start | end]])的第一個參數必須爲正整數,表示分幾步變化,第二個參數設置爲start時,表示在動畫開始執行時就進行變化,設置爲end表示在動畫通過transition-duration設置的時間纔開始變化,第二個參數容許省略,缺省值爲end。step-start至關於steps(1, start)即屬性一開始就變爲最終狀態;step-end至關於steps(1,end)即屬性通過transition-duration設置的時間後馬上變爲終止狀態。

#car{
    transition-property:width, height;
    transition-duration:1s, 3s;
    transition-timing-function: ease-in, cubic-bezier(1,0,0,1);
    transition-delay:2s, 0.5s;
}

可以使用transition縮寫簡化上例中的css,直接從W3C規範裏抄了下縮寫組成部分。

transition:<single-transition> [ ‘,’ <single-transition> ]*

<single-transition> = [ none | <single-transition-property> ] || <time> || <single-transition-timing-function> || <time>

第一個<time>對應transition-duration,第二個<time>對應transition-delay。
若是有一個<single-transition>裏的第一個參數設置爲none,則整個transition無效。也就是說none只能這麼用:transition:none

#car{
    transition:width 1s ease-in 2s, height 3s cubic-bezier(1,0,0,1) .5s;
}

animation

animation能夠說是transition的高級版,配合@keyframes能夠實現對動畫過程的多點控制。除了svg中延指定path路徑運動的動畫實現不了,其餘均可以用animation來實現。其不少屬性與svg的<animate>元素屬性做用也能一一對應。
先看下animation的屬性

  • animation-name

對應<animate>的attributeName屬性,屬性值爲@keyframes名對應,後面再說@keyframes

  • animation-duration

對應<animate>的dur屬性

  • animation-timing-function

對應<animate>的calcMode屬性,可用三次貝塞爾曲線來設置動畫運行的效果

  • animation-iteration-count

對應<animate>的repeatCount屬性。默認爲1。infinite表示無限重複(不一樣於repeatCount的indefinte)

  • animation-delay

動畫延遲執行時間。有點相似<animate>的start屬性的做用,用start加上一些事件和時間的計算,也能夠實現延遲執行動畫的效果

  • animation-fill-mode

相似<animate>的fill屬性,但有區別。animation-fill-mode有四個屬性值可選:none | forwards | backwards | both。

- **forwards**
 相似fill的freeze,動畫結束後保持最後一幀時的狀態。
 - **backwards**
 這個功能svg裏好像沒有。backwards是配合animation-delay一塊兒使用的,若是動畫延遲執行,那麼在開始執行以前處於延遲的這段時間內,動畫對象元素的默認狀態是其原始狀態,而非@keyframes的起始狀態。當animation-fill-mode設置成backwards時,動畫對象元素在延遲的這段時間內,將處於@keyframes設置的起始狀態。
 - **both**
 至關於同時設置了forwards和backwards兩個屬性值。
 - **none**
 none是animation-fill-mode的默認屬性值,即動畫開始前和動畫結束後,對象元素均處於其原始狀態。
  • animation-play-state

animation-play-state顧名思義控制動畫狀態的,兩個屬性值也好理解。

- **running**
表示讓動畫執行
- **paused**
表示暫停動畫
能夠經過改變這個屬性來控制動畫的播放和暫停,pause改成running後不會讓元素重頭再執行一遍動畫,而是接着暫停時的狀態繼續變化。
  • animation-direction

這個屬性用於控制動畫是正向執行,或者反向執行,若是設置了animation-iteration-count重複執行次數,還能控制一次動畫執行完畢後,以何種方式執行接下去的一次動畫。有四個屬性值normal | reverse | alternate | alternate-reverse

- **normal**
 默認屬性值,動畫正向執行,重複執行動畫時,每次都從起始狀態開始變化。
 - **reverse**
 動畫反向執行,即從指定的終止狀態變化到起始狀態,重複執行動畫時,每次都從終止狀態開始變化。其中animation-timing-function設置的運動曲線也會被顛倒,原來的ease-in會變成ease-out的效果。
 - **alternate**
 第一次執行動畫時,從起始狀態開始變化。重複執行動畫時,單次動畫結束後,下一次動畫以當前狀態做爲起始狀態開始變化,以上一次動畫的起始狀態做爲該次動畫的終止狀態,至關於執行一次reverse的動畫效果。
 - **alternate-reverse**
 和alternate相似,可是第一次執行動畫時,從指定的結束狀態開始向起始狀態變化。

能夠用animation來縮寫以上全部屬性:

animation:<single-animation> [ ‘,’ <single-animation> ]*

<single-animation> = <single-animation-name> || <time> || <single-animation-timing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state>

其中第一個<time>爲animation-duration,第二個<time>爲animation-delay。

再來看與animation緊密相關的@keyframes
@keyframes的做用相似values + keyTimes,可精細設置動畫過程當中每一個變化節點。
@keyframes必須包含一個動畫起始狀態信息,和一個動畫終止狀態信息。能夠用from + to,也能夠用0% + 100%:

@keyframes rotate1{
    from {
        left: 0;
        top: 0;
    }
    to {
        left: 100px;
        top: 100px;
    }
}
@keyframes rotate2{
    0% {
        left: 0;
        top: 0;
    }
    100%{
        left: 100px;
        top: 100px;
    }
}

以上兩段代碼等價,都表示起始狀態的left和top屬性爲0,終止狀態的left和top屬性爲100px。
對於中間動畫節點,好比在動畫進行到四分之一時,但願left爲50px:

@keyframes rotate2{
    0% {
        left: 0;
        top: 0;
    }
    50%{
        left: 50px;
    }
    100%{
        left: 100px;
        top: 100px;
    }
}

另外,還能夠對每段動畫的變化曲線作單獨設置animation-timing-function屬性,屬性須要設置在起始狀態信息中:

@keyframes rotate2{
    0% {
        left: 0;
        top: 0;
        animation-timing-function: ease-out;
    }
    50%{
        left: 50px; 
        animation-timing-function: ease-in;
    }
    100%{
        left: 100px;
        top: 100px;
    }
}
相關文章
相關標籤/搜索