深刻理解CSS動畫animation

前面的話

  transition過渡是經過初始和結束兩個狀態之間的平滑過渡實現簡單動畫的;而animation則是經過關鍵幀@keyframes來實現更爲複雜的動畫效果。本文將介紹關於animation動畫的相關知識css

 

定義

  和transition相似,animation也是一個複合屬性,包括animation-name、animation-duration、animation-timing-function、animation-delay、animation-iteration-count、animation-direction、animation-play-state、animation-fill-mode共8個子屬性html

  [注意]IE9-不支持;safari4-八、IOS3.2-8.四、android2.1-4.4.4須要添加-webkit-前綴android

animation-name: 動畫名稱(默認值爲none)
animation-duration: 持續時間(默認值爲0)
animation-timing-function: 時間函數(默認值爲ease)
animation-delay: 延遲時間(默認值爲0)
animation-iteration-count: 循環次數(默認值爲1)
animation-direction: 動畫方向(默認值爲normal)
animation-play-state: 播放狀態(默認值爲running)
animation-fill-mode: 填充模式(默認值爲none)
div{
    width: 300px;
    height: 100px;
    background-color: pink;
    animation-name: test;
    animation-duration: 3s;
    animation-timing-function: ease;
    animation-delay: 0s;
    animation-iteration-count: infinite;
    animation-direction: normal;
    animation-play-state: running;
    animation-fill-mode: none;
}
/* 關於keyframes關鍵幀的內容稍後介紹     */
@keyframes test{
    0%{background-color: lightblue;}
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
    100%{background-color: black;}
}

 

關鍵幀

  animation製做動畫效果須要兩步,首先用關鍵幀聲明動畫,再用animation調用動畫web

  關鍵幀的語法是以@keyframes開頭,後面緊跟着動畫名稱animation-name。from等同於0%,to等同於100%。百分比跟隨的花括號裏面的代碼,表明此時對應的樣式瀏覽器

@keyframes animation-name{
    from | 0%{}
    n%{}
    to | 100%{}
}

【1】百分比順序不必定非要從0%到100%排列,最終瀏覽器會自動按照0%-100%的順序進行解析app

  [注意]0%不能夠省略百分號函數

@keyframes test{
    100%{background-color: black;}
    60%{background-color: lightgray;}
    30%{background-color: lightgreen;}
    0%{background-color: lightblue;}
}
div{
    width: 300px;
    height: 100px;
    background-color: pink;
    animation-name: test;
    animation-duration: 3s;
    animation-iteration-count: infinite;
}

【2】若是存在負百分數或高於100%的百分數,則該關鍵幀將被忽略oop

/* -20%和120%對應的代碼無效*/
@keyframes test{
    -20%{background-color: red;}
    0%{background-color: lightblue;}
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
    100%{background-color: black;}
    120%{background-color: yellow;}
}

【3】若是0%或100%不指定關鍵幀,將使用該元素默認的屬性值測試

/* 0%和100%對應的顏色是默認值pink*/
@keyframes test{
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
}

【4】若存在多個@keyframes,瀏覽器只識別最後一個@keyframes裏面的值 動畫

/* 後面覆蓋前面 */
@keyframes test{
    0%{background-color: lightblue;}
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
    100%{background-color: black;}
}
@keyframes test{
    0%{background-color: blue;}
    30%{background-color: green;}
    60%{background-color: gray;}
    100%{background-color: black;}
}

【5】空的keyframes規則是有效的,它們會覆蓋前面有效的關鍵幀規則

/* 後面覆蓋前面 */
@keyframes test{
    0%{background-color: lightblue;}
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
    100%{background-color: black;}
}
@keyframes test{
}

 

動畫屬性

動畫名稱

animation-name

  值: none | <single-animation-name> [, <single-animation-name> ]*

  初始值: none

  應用於: 全部元素

  繼承性: 無

<single-animation-name>: none | 自定義動畫名稱

【1】若是多個動畫試圖修改相同的屬性,那麼動畫列表的後面覆蓋前面

/* animation-name的順序是test1,test2,且它們修改的是一樣的屬性,後面覆蓋前面,因此test2有效,test1無效 */
div{
    width: 300px;
    height: 100px;
    background-color: pink;
    animation-name: test1,test2;
    animation-duration: 3s;
    animation-iteration-count: infinite;
}
@keyframes test2{
    0%{background-color: blue;}
    30%{background-color: green;}
    60%{background-color: gray;}
    100%{background-color: black;}
}
@keyframes test1{
    0%{background-color: lightblue;}
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
    100%{background-color: black;}
}

【2】若是動畫的其餘7個子屬性和動畫名稱的長度不一樣,動畫名稱列表的長度決定最終的長度,多餘的值無餘,缺乏的值按照順序進行重複

div{
    width: 300px;
    height: 100px;
    position: relative;
    background-color: pink;
    animation-name: test1,test2,test3;
    animation-duration: 3s,1s;
    animation-iteration-count: infinite;
}
@keyframes test1{
    0%{background-color: lightblue;}
    30%{background-color: lightgreen;}
    60%{background-color: lightgray;}
    100%{background-color: black;}
}
@keyframes test2{
    0%{font-size: 20px;}
    30%{font-size: 30px;}
    60%{font-size: 40px;}
    100%{font-size: 50px;}
}
@keyframes test3{
    0%{left: 0px;}
    30%{left: 30px;}
    60%{left: 40px;}
    100%{left: 50px;}
}
<div>測試文字</div>    

 

持續時間

  持續時間指完成動畫的時間

animation-duration

  值: <time> [, <time>]*

  初始值: 0s

  應用於: 全部元素

  繼承性: 無

animation-duration: <time>[,<time>]*

  0s意味着動畫沒有時間,持續時間不能爲負值

animation-name: test1,test2;
/*test1的持續時間設置爲負值,將使得整個動畫持續時間都失效,所以test2也將沒有動畫效果 */
animation-duration: -1s,1s;

 

時間函數

animation-timing-function

  值: <single-timing-function> [, <single-timing-function>]*

  初始值: ease

  應用於: 全部元素

  繼承性: 無

  animation的時間函數相似於transition的時間函數。時間函數能夠應用於整個動畫中,也能夠應用於關鍵幀的某兩個百分比之間

div{
    width: 300px;
    height: 100px;
    position: relative;
    background-color: pink;
    animation-name: test;
    animation-duration: 5s;
    animation-iteration-count: infinite;
}

@keyframes test{
    0%{left: 0px;animation-timing-function: ease;}
    20%{left: 50px;animation-timing-function: linear;}
    40%{left: 100px;animation-timing-function: ease-in;}
    60%{left: 150px;animation-timing-function: ease-out;}
    80%{left: 200px;animation-timing-function: step-start;}
    100%{left: 250px;animation-timing-function: step-end;}
}

 

循環次數

animation-iteration-count

  值: infinite | <number>[,infinite | <number>]*

  初始值: 1

  應用於: 全部元素

  繼承性: 無

  默認爲1,能夠是整數也能夠小數,但不能是0和負數。若是爲infinite則表示無限次動畫

 

動畫方向

  動畫方向用來定義是否動畫須要反向播放

animation-direction

  值: <single-animation-direction>[,<single-animation-direction> ]*

  初始值: normal

  應用於: 全部元素

  繼承性: 無

<single-animation-direction> = normal | reverse | alternate | alternate-reverse
normal: 正向播放
reverse: 反向播放
alternate: 若動畫只播放一次,則和正向播放同樣。若播放兩次以上,偶數次效果爲反向播放
alternate-reverse: 若動畫只播放一次,則和反向播放同樣。若播放兩次以上,偶數次效果爲正向播放

  [注意]safari瀏覽器不支持reverse屬性和alternate-reverse屬性

 

動畫狀態

animation-play-state

  值:running | paused[,running | paused]*

  初始值: running

  應用於: 全部元素

  繼承性: 無

  running表示播放中,paused表示動畫暫停

 

延遲時間

  定義延遲多少時間後動畫開始播放

animation-delay

  值: <single-animation-delay>[,<single-animation-delay> ]*

  初始值: 0s

  應用於: 全部元素

  繼承性: 無

<single-animation-delay>= <time>[,<time>]*

  [注意]該延遲時間是指整個動畫的延遲時間,而不是每一個循環的延遲時間,只在動畫開始時進行一次時間延遲

  若是該值是負值,則表示動畫的起始時間從0s變爲延遲時間的絕對值

 

填充模式

  定義動畫開始幀以前和結束幀以後的動做

  [注意]android2.1-3不支持animation-fill-mode

animation-fill-mode

  值: <single-animation-fill-mode>[,<single-animation-fill-mode> ]*

  初始值: none

  應用於: 全部元素

  繼承性: 無

<single-animation-fill-mode> = none | forwards | backwards | both
none: 動畫結束後,元素移動到初始狀態
    [注意]初始狀態並非指0%的元素狀態,而是元素自己屬性值
forwards: 元素停在動畫結束時的位置
    [注意]動畫結束時的位置並不必定是100%定義的位置,由於動畫有可能反向運動,也有可能動畫的次數是小數
backwards:在animation-delay的時間內,元素馬上移動到動畫開始時的位置。若元素無animation-delay時,與none的效果相同
    [注意]動畫開始時的位置也不必定是0%定義的位置,由於動畫有可能反向運動。
both: 同時具備forwards和backwards的效果

  [注意]當持續時間animation-duration爲0s時,animation-fill-mode依然適用,當animation-fill-mode的值爲backwards時,動畫填充在任何animation-delay的階段。當animation-fill-mode的值爲forwards時,動畫將保留在100%的關鍵幀上

 

多值

animation

  值: <single-animation>[,<single-animation> ]*

  初始值: 無

  應用於: 全部元素

  繼承性: 無

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

  [注意]持續時間在前,延遲時間在後,若只存在一個時間,則是持續時間

div{
    width: 300px;
    height: 100px;
    background-color: pink;
    animation: 1s test1,infinite test2 2s 1s;
}
@keyframes test1{
    30%{background-color: red;}
    60%{background-color: blue;}
    100%{background-color: green;}
}
@keyframes test2{
    100%{color: white;}
}

 

API

  animation涉及到的事件有animationstart、animationend、animationiteration三個。這三個事件的bubbles都是yes,cancelable都是no

  [注意]對於safari瀏覽器,animation的事件爲webkitAnimationStart、webkitAnimationEnd、webkitAnimationIteration

  [注意]動畫事件只支持DOM2級事件處理程序的寫法

animationstart

  發生在動畫開始時

  【1】若是存在delay,且delay爲正值,則元素等待延遲完畢後,再觸發該事件

  【2】若是delay爲負值,則元素先將初始值變爲delay的絕對值時,再觸發該事件

    oSb.addEventListener('animationstart',function(){
        this.innerHTML = '動畫開始';
        this.style.background = 'lightgreen';
    },false);

 

animationend

  發生在動畫結束時

test.addEventListener('animationend',function(){
    this.style.background="lightgreen";
    this.innerHTML = '動畫結束';
},false);

 

animationiteration

  發生在動畫的一次循環結束時,只有當iteration-count循環次數大於1時,觸發該事件

var i = 0;
oSb.addEventListener('animationiteration',function(){
    i++;
    this.innerHTML = i;
},false);

【補充】

  只有改變animation-name時,纔會使animation動畫效果從新觸發

oSb.style.animationName = 'none';
setTimeout(function(){
    oSb.style.animationName = 'test';
},100);

屬性

  這三個事件的事件對象,都有animationName和elapsedTime屬性這兩個私有屬性

animationName屬性:返回產生過渡效果的CSS屬性名
elapsedTime屬性:動畫已經運行的秒數

  [注意]對於animationstart事件,elapsedTime屬性等於0,除非animation-delay屬性等於負值

<style>
#test{height:100px;width:300px;background-color:lightblue;animation:anim 2s 3;}
@keyframes anim{
    0%{height: 100px;}
    50%{height: 50px;}
    100%{height: 0;}
}
</style>

<button id='reset'>還原</button>
<div id="test"></div>
<script>
reset.onclick = function(){
    history.go();
}
test.addEventListener("animationstart", listener, false);
test.addEventListener("animationend", listener, false);
test.addEventListener("animationiteration", listener, false);
function listener(e){
    e = e || event;
    var li = document.createElement("li");
    switch(e.type) {
    case "animationstart":
      li.innerHTML = "Started: elapsed time is " + e.elapsedTime;
      break;
    case "animationend":
      li.innerHTML = "Ended: elapsed time is " + e.elapsedTime;
      break;
    case "animationiteration":
      li.innerHTML = "New loop started at time " + e.elapsedTime;
      break;
    }
    test.appendChild(li);
}
</script>
相關文章
相關標籤/搜索