跳到主要內容
黯羽輕揚每天積累一點點

animation

免費2016-12-03#CSS#CSS animation#animation-fill-mode#animation-play-state#CSS3闪烁动画

CSS animation 的定義方式和 Flash 非常相似,比如 Flash 中的關鍵影格、空白關鍵影格、普通影格

一.CSS 動畫

CSS 動畫相對 JS 動畫有 2 個主要優勢:

1.流暢

因為渲染引擎可以透過跳影格(frame-skipping)及其它技術來確保效能盡量流暢

2.瀏覽器效能優化

把動畫序列交給瀏覽器去控制,這樣瀏覽器就能優化效能和效率,比如對於看不見的 tab,可以減少刷新頻率

定義動畫分為 2 部分

  • 配置 animation 各項子屬性

  • 透過 @keyframes 定義關鍵影格樣式

瀏覽器根據這些東西來建立補間動畫,計算插值把各個關鍵影格連接起來

二.animation 子屬性

animation-name @keyframes 定義的關鍵影格名,預設 none
animation-duration 動畫時長,預設 0s,與 transition 完全一致
animation-timing-function easying 函數,預設 ease,與 transition 完全一致
animation-delay 延遲時間,預設 0s,,與 transition 完全一致
animation-iteration-count 重複次數,預設 1
animation-direction 方向,預設 normal
animation-fill-mode 樣式套用模式,預設 none
animation-play-state 用來暫停/恢復動畫序列,預設 running

需要注意:

  • durationdelay,其它參數順序隨意

  • animation-name 不要和關鍵字重名,會優先比對屬性

animation-iteration-count

animation-iteration-count = infinite | <number>

動畫重複次數,各值分別表示無限次、指定次數

animation-direction

animation-direction = normal | reverse | alternate | alternate-reverse

動畫執行方向,各值分別表示正向、反向、交替(奇數次正向偶數次反向)、反向交替(奇數次反向偶數次正向)

animation-fill-mode

animation-fill-mode = none | forwards | backwards | both

樣式套用模式,各值分別表示不套用關鍵影格樣式、(結束後)套用終態樣式、(delay 期間)套用初態樣式、(delay 期間)套用初態樣式且(結束後)套用終態樣式

注意:初態和終態可能是 0% 也可能是 100%,由 animation-iteration-countanimation-direction 共同決定

關鍵字含義如下:

none 在動畫結束後,去掉 @keyframes 定義的樣式,恢復原樣式
forwards 在動畫結束後,保持終態樣式
backwards 在動畫開始前(delay 期間),保持初態樣式
both 同時具有 forwards 和 backwards 的效果,即在 delay 期間保持初態樣式,在動畫結束後保持終態樣式

具體差異見 Demo:http://www.ayqy.net/temp/animation/animation-fill-mode.html,點擊紅色塊開始動畫

animation-play-state

animation-play-state = running | paused

決定動畫執行還是暫停,可以用來控制動畫暫停/恢復,比 delay 更強大更靈活一些

具體效果見 Demo:http://www.ayqy.net/temp/animation/animation-play-state.html

三.@keyframes

語法如下:

@keyframes anmiationName {
    0% {}
    /*...*/
    100% {}
}

如果沒有定義 0%100%,瀏覽器就根據其它時刻的關鍵影格給所有屬性算一組值

P.S. tofrom 分別是 0%100% 的別名,因為初態和終態比較重要,有權申請英文名

四.事件

transition 只有一個 end 事件,animation 提供了 3 個事件:

animationstart      開始
animationend        結束
animationiteration  開始下一次重複

事件物件有 3 個特殊屬性:

  • animationName

    animation-name

  • elapsedTime

    單位是秒,對於 animationstartanimationend 表示動畫執行到此刻的時間,對於 animationiteration,表示下一次重複開始的時間,與 transitionend 事件類似,一般不受 delay 影響

    特殊的,animationstart 中的 elapsedTime 一般為 0,除非 animation-delay 是個負值,此時 elapsedTime-1 * delay

  • pseudoElement

    :: 開頭的偽元素名,如果動畫不是套用在偽元素上,就是空字串

注意:最後一次重複結束的時候,不會觸發 animationiteration,而是觸發 animationend

五.技巧

1.steps(1) 去掉平滑過渡

steps(1)linear 很像,去掉一個 linear 動畫的補間過渡,只留下關鍵影格,關鍵影格之間的影格延續上一個關鍵影格,就得到了 steps(1)

製作 Flash 時,先插入兩個關鍵影格,此時兩個關鍵影格之間的都是普通影格(用來延長上一個關鍵影格的播放時間),這時的效果就是 steps(1)。右鍵後一個關鍵影格,建立補間動畫,此時得到的就是 linear 效果

實例如下:

.rgb {
    -webkit-animation: rgb 1.5s linear infinite;
    animation: rgb 1.5s linear infinite;
}
@keyframes rgb {
    0% {
        opacity: red;
    }
    33% {
        background: green;
    }
    66% {
        background: blue;
    }
}

效果是背景色紅綠藍平滑漸變,想去掉漸變的平滑過渡,直接把 linear 改為 steps(1) 即可,如下:

.rgb-step {
    -webkit-animation: rgb 1.5s steps(1) infinite;
    animation: rgb 1.5s steps(1) infinite;
}

效果就變成了每 0.5 秒切換一次背景色,沒有漸變過渡

具體應用:兩種狀態無限切換(閃爍)

.blink {
    -webkit-animation: blink 1s steps(1) infinite;
    animation: blink 1s steps(1) infinite;
}
@keyframes blink {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
}

2.添加關鍵影格去掉平滑過渡

閃爍效果有另一種有趣的實現方式:

.blink {
    -webkit-animation: blink 1s linear infinite;
    animation: blink 1s linear infinite;
}
@keyframes blink {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 0;
    }
    50.01% {
        opacity: 1;
    }
    100% {
        opacity: 1;
    }
}

雖然還是 linear 平滑過渡,但插入的:

50.01% {
    opacity: 1;
}

去掉了 50% -> 100% 的補間,把透明度補間轉移到 50% -> 50.01%,時間較短的情況下,這個補間變化不會被察覺,當然,如果時間足夠長,比如:

.blink {
    -webkit-animation: blink 10000s linear infinite;
    animation: blink 10000s linear infinite;
}

就應該能看到透明度在某 1 秒內從 0 漸變到 1,但一般情況下,這樣實現閃爍在效果上是沒有問題的

3.關鍵影格控制延遲

animation-delay 只在動畫開始前有效,每次重複不會插入延遲。類似於上面 50.01% 的技巧,可以透過插入空白關鍵影格來給每次重複插入延遲,實現 loading 轉一圈等一等的效果:

.wait {
    -webkit-animation: wait 1s linear infinite;
    animation: wait 1s linear infinite;
}
@keyframes wait {
    0% {
        -webkit-transform: rotateZ(0);
        transform: rotateZ(0);
    }
    40% {
        -webkit-transform: rotateZ(0);
        transform: rotateZ(0);
    }
    100% {
        -webkit-transform: rotateZ(360deg);
        transform: rotateZ(360deg);
    }
}

做到了每轉一圈等 0.4s

4.steps 逐影格動畫

把序列影格平鋪在一張圖片上,修改 background-position

steps() 實現的話需要在末尾複製第一影格(比如 6 影格動畫,需要 7 影格平鋪圖),例如:

.walk {
    background: url(walk.svg);
    width: 162px;
    height: 230px;

    -webkit-animation: walk 1s steps(22) infinite;
    animation: walk 1s steps(22) infinite;
}
@keyframes walk {
    0% {
        background-position: 0 0;
    }
    100% {
        background-position: -3564px 0;
    }
}

其中 walk.svg 橫向鋪滿了 23 影格,每影格尺寸是 162 * 230,向左抽背景圖片,最多能抽 162 * 22 = 3564,此時顯示最後一影格(圖片影格內容與第一影格相同),首尾接起來

當然,還有另一種方法,用 steps(1) 去掉平滑過渡,然後手動設置 22 個關鍵影格,比較費勁,這裡不給例子,但肯定是可行的

線上 Demo:http://www.ayqy.net/temp/animation/css-animation-tricks.html

六.總結

CSS animation 的定義方式和 Flash 非常相似,比如 Flash 中的幾個概念:

  • 關鍵影格:如果你希望某處的內容要跟前面不一樣,就插入關鍵影格

  • 空白關鍵影格:表示上面沒內容,以小白點顯示。他可以跟關鍵影格互相轉換,放了內容就成關鍵影格了。關鍵影格上的內容去掉就是空白關鍵影格

  • 普通影格:關鍵影格或者空白關鍵影格後面延續的是普通影格。普通影格是延續之前關鍵影格的內容,所以他的作用可以用來控制動畫的顯示時間

對應到 CSS 的 @keyframes 定義中感受一下,是不是有點意思?

參考資料

評論

暫無評論,快來發表你的看法吧

提交評論