CSS 3学习——animation动画
以下內容根據官方文檔翻譯以及自己的理解整理。
1. 介紹
本方案介紹動畫(animations)。通過動畫,開發者可以將CSS屬性值的變化指定為一個隨時間變化的關鍵幀(keyframes)的集合。在隨著時間變化而改變CSS屬性值呈現方面,動畫與過渡(transitions)類似。主要的區別是,當CSS屬性值改變時,過渡隱式觸發;而當動畫屬性被應用時,動畫被顯式地執行。正因為如此,在給CSS屬性添加動畫時,需要給動畫指定明確的值。
動畫的許多方面都可以被控制,包括動畫的重復次數,是否在開始值與結束值之間交替,以及是否讓動畫開始或暫停。同樣也可以控制動畫是否延遲開始。
2. 動畫
CSS動畫影響屬性值的計算。這種影響通過向CSS層疊順序中添加一個指定的值實現,這樣就可以產生動畫在當前狀態的正確的計算值。正如[CSS3CASCADE]中規定的那樣,動畫會覆蓋所有正常的樣式規則,但是動畫會被 !important規則覆蓋。
如果在某一時刻對于同一個CSS屬性存在多個指定的動畫行為,那么此刻在animation-name屬性值中最后出現的動畫會覆蓋其他的動畫。
例子 點我看效果
div{
300px;
height: 100px;
background-color: red;
margin-bottom: 10px;
}
#div1{
animation-name: test1,test2;
animation-duration: 3s,3s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in;
animation-delay: 0s;
}
@keyframes test1{
0%{ 300px;}
100%{
500px;
background-color:#fff;
}
}
@keyframes test2{
0%{ 300px;}
30%{ 400px;}
60%{ 450px;}
100%{
800px;
background-color:black;
}
}
<div id="div1"></div>
以下兩種情形,動畫不會影響屬性值的計算:在應用一個動畫之前(也就是說,當animation-name屬性被聲明到一個元素上時)或者將動畫移除之后。此外,在動畫的延遲時間結束之前或者動畫結束之后,動畫也不會影響屬性值的計算,但是這取決于animation-fill-mode屬性。
在運行期間,動畫會計算相應屬性的值。根據CSS層疊規則,其他屬性的值可能會優先于動畫值(比如!important)。
當一個動畫被應用但是還沒有結束時,或者已經結束了,但是其animation-fill-mode的值為forwards或者both,,此時用戶代理必須表現得好像該元素的will-change屬性追加包含所有的指定了動畫的屬性。
動畫的開始時刻(start time)是應用了動畫(animation)的樣式屬性以及相應的關鍵幀規則(@keyframes rule)被解析(be resolved)的時刻。如果一個動畫被指定到一個元素上,但是相應的關鍵幀規則還不存在,那么這個動畫就不會開始;一旦相對應的關鍵幀規則可以被解析,動畫就會開始。通過動態修改元素的樣式產生的動畫會在對應的樣式被解析時開始;比如偽樣式規則(:hover,用偽類觸發動畫),或者通過腳本應用的樣式(用JS給元素添加animation-name)。注意,動態地更新關鍵幀樣式規則(keyframe style rules)不會開始或重啟一個動畫,只有通過修改animation-name屬性才會重啟動畫。
如果一個動畫的名字是animation-name屬性計算值標識符中的一個,而且該動畫使用一個有效的@keyframe規則,那么該動畫會被成功應用到元素上。一旦一個動畫開始,他將持續下去直到結束或者animation-name屬性被移除為止。
筆記:通過animation-name控制動畫的觸發。
在動畫運行過程中改變動畫屬性的值(animation-*),那么這個動畫表現得就好像一開始就是被指定了這些值一樣(也就是說動畫會使用修改后的值繼續動畫)。比如,減小animation-delay的值,也許會導致動畫向前跳躍或者甚至立即結束并且觸發一個animationend事件。相反,增大animation-delay的值可能導致動畫重新開始并觸發一個animationstart事件。 點我看示例
相同名字的動畫可能在animation-name中重復出現。animation-name值的變更會導致從新動畫列表(就是當前animation-name屬性的值列表)的最后一個標識符向第一個進行遍歷從而對現存已有的動畫(用@keyframes定義的動畫)進行更新。對于每一個動畫,找到其在新動畫列表中的最靠后的匹配項(the last matching animation)。如果存在這個匹配項,則使用該位置對應的其他的動畫屬性(animation-*)的值對現有已存在的動畫進行更新;同時,保存動畫當前的播放時間(playback time)。把匹配到的動畫從新動畫列表中移除,防止二次匹配。如果不存在這個匹配項,就創建一個新的動畫。結果是更新animation-name:從“a”到“a, a”,這將導致已有的動畫“a”變成動畫列表中的第二個動畫,并且在列表的第一個位置會創建一個新的動畫。
上面這段話的大概意思是:如果animation-name中有重復的動畫名,則以最靠后一個為準,前面的重復項只占據位置用于匹配其他animation-*屬性的值,不執行。
例子
div {
animation-name: diagonal-slide;
animation-duration: 5s;
animation-iteration-count: 10;
}
@keyframes diagonal-slide {
from {
left: 0;
top: 0;
}
to {
left: 100px;
top: 100px;
}
}
這個例子會產生一個把元素從(0, 0)位置移動到(100, 100)位置的動畫。完成一次動畫用時5s,總共執行10次。
把元素的display屬性值設為none會停止任何添加在其自身和后代元素上的動畫。如果把一個元素的display屬性的值由none更改為其他不是none的值,通過animation-name屬性添加到該元素上的所有動畫都會開始運行,同樣其display不為none的后代元素的動畫也會開始運行。
3.Keyframes 關鍵幀
對于動畫屬性(animation-*)來說,關鍵幀用于指定動畫在運行期間不同時間點的值。關鍵幀指定了動畫一個完整周期的行為,一個動畫可能重復0次或更多次。
使用@keyframs指定關鍵幀,語法如下:
@keyframes = @keyframes <keyframes-name> { <rule-list> }
<keyframes-name> = <custom-ident> | <string>
<keyframe-block> = <keyframe-selector># { <declaration-list> }
<keyframe-selector> = from | to | <percentage>
@keyframes中的<rule-list>只能包含<keyframe-block>。
<keyframe-block>中的<declaration-list>接受任何規范中定義的CSS屬性。<declaration-list>中的樣式屬性不與外部樣式屬性相互作用(所以在這里對屬性應用!important是無效的,反而會使屬性被忽略)。
<custom-ident> 或<string>定義了@keyframes塊的名字。這兩種語法在功能上是等價的:塊的名字是標識符或字符串。<custom-ident> 和<string>區分大小寫,只有當兩個名字codepoint-by-codepoint(碼點對碼點)相等時,才說這兩個名字相等。<custom-ident>不可以用關鍵詞“none”。
例子
/*下面兩個@keyframes有相同的名字,所以第一個將被忽略*/
@keyframes foo { ... }
@keyframes "foo" { ... }
/*下面這個@keyframes的名字與前面兩個的不同*/
@keyframes FOO { ... }
/*下面兩個@keyframes的名字都是無效的,因為用了<custom-ident>不允許用的值:*/
@keyframes initial { ... }
@keyframes None { ... }
/*然而,如果將上面兩個@keyframes的名字指定為<string>將是有效地:*/
@keyframes "initial" { ... }
@keyframes "None" { ... }
對于一個<keyframe-block>的<keyframe-selector>,由百分比值或者關鍵字from或to組成。<keyframe-selector>用于指定在動畫時間(the duration of the animation)相應的百分比處要出現的關鍵幀。在<keyframe-selector>后跟的大括號 {} 中用樣式屬性指定關鍵幀。關鍵詞from相當于0%,關鍵詞to相當于100%。如果<keyframe-selector>小于0%或者大于100%將會使該<keyframe-block>無效。注意:用百分數作為<keyframe-selector>(關鍵幀選擇器)時,必須要帶%,否則該關鍵幀無效。
如果沒有指定0%或from關鍵幀,那么用戶代理會用添加了動畫的屬性的計算值創建一個0%處的關鍵幀。如果100%或to關鍵幀沒有被指定,那么用戶代理會用添加了動畫的屬性的計算值創建一個100%處的關鍵幀。
<keyframe-block>中包含CSS屬性及其值,即通常說的CSS規則。除了animation-timing-function屬性外,其他的動畫屬性(animation-*)在這些規則中將會被忽略,后面內容會詳細描述。另外帶有!important的屬性是無效的,同樣會被忽略。
如果多個@keyframes被指定了同樣的名字,在文檔順序中的最后一個會勝出,在此之前的所有同名的@keyframes都會被忽略。
例子
div {
animation-name: slide-right;
animation-duration: 2s;
}
@keyframes slide-right {
from {
margin-left: 0px;
}
50% {
margin-left: 110px;
opacity: 1;
}
50% {
opacity: 0.9;
}
to {
margin-left: 200px;
}
}
/*在1s時,動畫slide-right的狀態與下面定義的動畫相同:*/
@keyframes slide-right {
50% {
margin-left: 110px;
opacity: 0.9;
}
to {
margin-left: 200px;
}
}
為了確定關鍵幀的集合,所有關鍵幀規則根據擇器的值按照時間增加排序,那么在@keyframes中的規則就形成一個級聯。一個關鍵幀里的屬性可能來源于多個有相同選擇器值的關鍵幀規則(比如上例中有兩個選擇器為50%的關鍵幀規則)。如果一個屬性沒有在關鍵幀中指定,或者指定了無效的關鍵幀,那么該屬性的動畫運行時就好像對應的關鍵幀不存在一樣。從概念上講,好像是為關鍵幀規則中出現了的屬性都創建了一個關鍵幀集合。對每一個(有關鍵幀集合的)屬性,其動畫都是獨立運行的。
例子
@keyframes wobble {
0% {
left: 100px;
}
40% {
left: 150px;
}
60% {
left: 75px;
}
100% {
left: 100px;
}
}
這個例子中給名為wobble的動畫指定了4個關鍵幀。第一個關鍵幀在一個動畫周期的開始時出現,此時left屬性的值是100px。動畫時間(animation duration)到40%時,left的值為150px。動畫時間到60%時,left的值回到75px。在一個動畫周期結束時,left的值回到100px。下面的圖示展示了動畫時間為10s時,這個動畫的狀態:
Animation states specified by keyframes
3.1. timing function for keyframes
在一個關鍵幀樣式規則中可以聲明timing function用于描述動畫如何過渡到下一幀。
例子
@keyframes bounce {
from {
top: 100px;
animation-timing-function: ease-out;
}
25% {
top: 50px;
animation-timing-function: ease-in;
}
50% {
top: 100px;
animation-timing-function: ease-out;
}
75% {
top: 75px;
animation-timing-function: ease-in;
}
to {
top: 100px;
}
}
名為bounce的動畫指定了5個關鍵幀。在第一個和第二個關鍵幀之間(即0%與25%之間)的timing function用了ease-out。在第二個和第三個關鍵幀之間(即25%與50%之間)的timing function用了ease-in。效果是元素先逐漸減速向上移動50px,然后再加速向下掉回到100px處。動畫的第二部分以類似的方式運行,但是元素只移動25px。
在to或100%處的關鍵幀中指定的timing function將會被忽略(不管動畫是正向播放還是反向播放)。詳情見animation-timing-function屬性部分。
3.2. animation-name屬性
animation-name屬性定義了一個應用動畫的名字列表。列表中的每一個名字用于選擇給動畫提供屬性值的同名@keyframes規則。如果有名字沒有匹配到任何同名@keyframes,那么沒有屬性會被動畫化,這個名字的動畫也不會運行。此外,如果列表中有動畫的名字為none,那么也不會有動畫。
如果有多個動畫修改了同一個屬性的值,那么在名字列表中最靠后的那個動畫會勝出。
在列表中的動畫都應該有對應的其他動畫屬性(animation-*)值。如果其他動畫屬性的值列表長度與animation-name屬性的值列表長度不一樣長,那么動畫開始時,animation-name的值列表長度決定其他動畫屬性的值列表長度。按照動畫名字在值列表中的位置從第一個開始匹配其他動畫屬性的值,最后多余的值被忽略。如果其他動畫屬性的值不足以匹配列表中所有的動畫名字,那么用戶代理會從頭重復動畫屬性的值直到能夠滿足匹配。其他動畫屬性值的截斷和重復不會影響計算值。
animation屬性
值:[ none | <keyframes-name> ]#
動畫名字之間用逗號分隔。
適用于:所有元素, ::before和::after偽元素
不可繼承
默認值:none
none
表示沒有動畫。
<keyframes-name>
逗號分隔的動畫名字列表。如果沒有對應的同名@keyframes,則沒有動畫。
關于值的匹配看下面例子:
div{
300px;
height: 100px;
background-color: pink;
animation-name: test2,wow,test1,test2;
animation-duration:1s,3s,0s,0s;
animation-iteration-count: infinite;
}
@keyframes test2{
0%{background-color: blue;}
30%{background-color: green;}
60%{background-color: gray;}
100%{background-color: black;}
}
<div id="div1"></div>
在chrome和Firefox下是有動畫效果,IE中沒有動畫效果。
補充:transition也有上面這種相同情形的例子。
3.3. animation-duration屬性
annnimation-duration屬性指定一次動畫周期的時間。
值:<time> #
默認值:0s
適用于:all elements, ::before and ::after pseudo-elements
不可繼承
<time>
表示一次完整動畫周期的時長,負值會使整個animation-duration屬性無效。
如果值為0s,對應動畫的關鍵幀沒有效果,但實際上動畫還是運行了。特別地,開始事件和結束事件也被觸發了。如果animation-fill-mode的值被設為了backwards或both,那么動畫(在animation-duration時間開始時)的第一幀會在animation-delay期間顯示。如果animation-fill-mode的值被設為了forwards或者both,那么動畫(在animation-duration時間結束時)的最后一幀也會顯示。如果animation-fill-mode的值被設為none,那么這個動畫沒有視覺上的效果。
關于上面這段話的驗證看這個演示:demo。
animation-duration為0s時還是可以觸發animationstart事件和animationend事件,不會觸發animationiteration。
3.4. animation-timing-function屬性
屬性animation-timing-function用于描述動畫如何從當前幀過渡到下一幀。
該屬性的取值與transition-timing-function屬性的取值一樣。
默認值為:ease
適用于:all elements, ::before and ::after pseudo-elements
不可繼承
timing function應用于動畫的關鍵幀之間。
如果在一個關鍵幀中指定了animation-timing-function,意思是動畫在當前方向上從該關鍵幀向下一個關鍵幀過渡時要使用的timing function。
對于在0%與100%之間指定了關鍵幀的動畫來說,timing function作用于一個關鍵幀周期而非整個動畫周期,即作用于從一個關鍵幀開始到下一個關鍵幀開始。
特別地,不管動畫是正向播放還是反向播放,在to或100%的關鍵幀中指定的timing function會被忽略。
例子 在線演示
div{
width: 100px;
height: 100px;
background-color: pink;
margin-bottom: 10px;
}
#div3{
animation-name: test3;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-direction: alternate ;
animation-timing-function: ease-in;
background-color: yellow;
animation-delay: 0s;
}
@keyframes test3{
0%{
width: 100px;
}
50%{width: 400px;background-color:red;}
100%{
width: 700px;
animation-timing-function:linear;
}
}
3.5. animation-iteration-count屬性
屬性animation-iteration-count指定一個完整動畫周期的播放次數。
這個屬性通常與值為alternate的屬性animation-direction一起用。
默認值為1,表示動畫只播放一次。
適用于:all elements, ::before and ::after pseudo-elements
不可繼承。
取值可以是逗號分隔的值列表,也可以是單值。
infinite
表示動畫無限次重復。
<number>
動畫會播放指定數字的次數。如果數字不是整數,動畫會在最后一次播放的中途停止。負值會使整個屬性無效。
如果值為0,與animation-duration為0s時類似,使動畫在瞬間完成,可以觸發animationstart事件和animationend事件,不會觸發animationiteration事件。
3.6. animation-direction屬性
屬性animation-dirction定義動畫的整個周期或部分周期是否反向播放。當動畫反向播放時,timing function也是反向的。
比如,反向播放ease-in的動畫時,好像是在播放一個ease-out的動畫。
取值:<single-animation-direction> #
默認值:normal
適用于:all elements, ::before and ::after pseudo-elements
不可繼承
<single-animation-direction> = normal | reverse | alternate | alternate-reverse
normal
每個播放周期動畫都正向播放。換言之,每個動畫周期結束,動畫重置到起點重新開始。
reverse
每個播放周期動畫都反向播放。
alternate
動畫在第奇數次播放時正向播放;在第偶數次播放時反向播放。
alternate-reverse
動畫在第奇數次播放時反向播放;在第偶數次播放時正向播放。
注意:這里默認animation-iteration-count不為0。
3.7. animation-play-state屬性
屬性animation-play-state定義動畫是運行還是暫停。
值:<single-animation-play-state> #
默認值:running
適用于:all elements, ::before and ::after pseudo-elements
不可繼承
<single-animation-play-state> = running | paused
running
表示動畫正常運行。
paused
當該屬性的值為paused時,動畫處于暫停狀態。暫停之前,元素上的動畫過程正常運行。當把值改回running時,動畫從它停止的位置繼續播放,就像有一個計時器在控制動畫的暫停和開始一樣。
如果在動畫的延遲期間把該屬性的值設為paused,則延遲計時器也會暫停;當把animation-play-state的值再改回running,延遲計時器繼續計時。
點擊看示例
3.8. animation-delay屬性
屬性animation-delay指定動畫什么時候開始。
值: <time> #
默認值為0s。
適用于:all elements, ::before and ::after pseudo-elements
不可繼承。
<time>
<time>定義在動畫開始(動畫應用到元素上的時刻,the start of the animation)與動畫開始播放之間的延遲時間。該值可用單位為秒(s)和毫秒(ms)。
默認值0s表示動畫應用到元素上后立即播放。
負值也是有效的。如果為負值,動畫也會立即開始播放。但是,不是從0%開始播放,而是從中途的某一幀開始播放。例如,如果animation-delay設定值為-1s,animation-duration設為2s,那么動畫會從50%處立即開始播放。
If you specify a negative value for the animation delay, but the starting value is implicit, the starting value is taken from the moment the animation is applied to the element.
筆記:the start of the animation (when the animation is applied to the element via these properties) equal to the animation-name property is set on an element
3.9. animation-fill-mode屬性
屬性animation-fill-mode用來指定在動畫播放時間之外給動畫的目標應用什么的樣式值。
默認情況下,在延遲期間,動畫不會影響樣式屬性的值。同樣,默認情況下,動畫結束播放之后也不會影響樣式屬性的值。
animation-fill-mode屬性可以覆蓋上述行為。不管是在動畫的延遲期間還是動畫結束之后都可以根據需要指定元素的樣式。
值:<single-animation-fill-mode> #
默認值:none
適用于:all elements, ::before and ::after pseudo-elements
不可繼承。
<single-animation-fill-mode> = none | forwards | backwards | both
none
動畫播放前和結束后不改變元素的任何樣式。
forwards
元素應用動畫結束時那一幀的樣式。animation-interation-count屬性和animation-direction屬性都會影響動畫結束時那一幀的樣式。
當animation-interation-count大于0時,不管是整數還是小數,不管是正向還是反向,元素就是應用動畫結束時那一幀的樣式。
當animation-interation-count為0時,元素會應用0%對應那一幀的樣式。
backwards
在延遲期間內,元素會應用動畫播放時第一幀的樣式。
當animation-direction為normal或alternate時,元素會應用0%對應那一幀的樣式;當animation-direction為reverse或alternate-reverse時,元素會應用100%對應那一幀的樣式。
both
元素同時應用forwards和backwards時的樣式。
3.10. animation屬性
簡寫屬性animation的值是一個逗號分隔的動畫描述的列表。列表中的每一個項目對應一個動畫,其中包含各子動畫屬性的值。
值:<single-animation> #
默認值:參見前面介紹的各子屬性。
適用于:all elements, ::before and ::after pseudo-elements
不可繼承。
<single-animation> = <time> || <single-timing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ]
注意:列表中<time>類型的值的順序很重要,第一個<time>代表animation-duration的值,第二個<time>代表animation-delay的值。如果只指定了一個<time>,則代表animation-duration的值,animation-delay使用默認值。
注意:不要使用關鍵字作為動畫的名字。
4.Animation Event
通過DOM的事件系統可以使用幾個與動畫相關的事件。動畫的開始和結束,以及動畫每一次重復的結束都會產生DOM事件。
一個元素同時可以有多個屬性被指定動畫(可以是在一個動畫中指定多個屬性也可以是在多個動畫中指定多個屬性)。對于事件而言,事件是相對于一個動畫產生的(不管這個動畫中指定了幾個屬性),而不是相對于一個指定了動畫的屬性產生的。
只要動畫中定義的關鍵幀是有效的(包括空的關鍵幀),那么這個動畫在運行時都會產生事件。
動畫已經運行的時間會分發給每一個事件,這可以使事件處理程序(event handler)區分一個重復播放的動畫當前的播放是否是重復的播放,或者一個交替播放的動畫當前的位置。這個時間不包含動畫在暫停狀態停留的時間。
4.1.動畫事件接口
4.1.1屬性
animationName
只讀,字符串類型
返回animation-name屬性的值中觸發事件的那個動畫的名字。
elapsedTime
只讀,浮點數
返回觸發事件時動畫已經運行的時間,單位s,不包括動畫暫停的時間。
pseudoElement
返回添加動畫的偽元素(以兩個冒號開始)的名字(這種情況下事件的目標(target)是于偽元素相關的真實元素)。
如果添加了動畫的元素不是偽元素則返回空字符串,時間的目標就是該元素。
4.2 動畫事件類型
動畫事件只能用DOM2級的添加事件的方法添加。
aniamtionstart
animationstart事件在動畫開始播放時觸發。如果動畫有animation-delay指定的延遲時間,那么該事件在延遲時間結束時觸發。
如果animation-delay為負值,則該事件的elapsedTime返回animation-delay的絕對值。
animationend
動畫播放完成以后觸發animationend事件。
該事件的elapsedTime屬性的返回值等于animation-duration的值乘以animation-iteration-count的值。
animationiteration
該事件在動畫的每一次重復結束時觸發(測試最后一次重復的結束就不會觸發,最后一次重復的結束觸發animationend事件)。
如果animation-iteration-count的值小于等于1不會觸發該事件。
此外,如果animation-delay的值為負,根據animation-duration和animation-iteration-count的值的大小,也會影響animationiteration事件的觸發。
ps:上面這句話有多種情形,有點復雜,只是大概測試了一下。
該事件的elapsedTime返回當前播放次數與animation-duration的乘積。
最后,還有一個animationcancel事件,目前還沒有瀏覽器支持。
總結
以上是生活随笔為你收集整理的CSS 3学习——animation动画的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电信光猫怎么跟别的路由器桥接光猫如何接收
- 下一篇: 路由器有线桥接教程详细如何打开有线桥接路