今年我面試了不少同窗,只要看到簡歷上寫「熟練掌握CSS3」的,我都會問問動畫相關知識。然而我發現:都 2019
年了,還有不少同窗不會 CSS
動畫。css
我常常愛問的一個問題是,實現以下的效果:面試
即,一個小球從向右勻速移動 200px
,而後移動回來,再移動過去,最後停留在 200px
處。canvas
動圖效果以下:
瀏覽器
就是需求這麼簡單的一個動畫,然而絕大多數人卻不能答對。app
不賣關子,個人答案是:函數
div{
width: 40px;
height: 40px;
border-radius: 50%;
background: #0ff;
animation: move 2s linear 3 alternate both;
}
@keyframes move{
0%{
transform: translate(0,0);
}
100%{
transform: translate(200px,0);
}
}
複製代碼
大部分面試者說,關於 CSS
動畫,也看過一些教程,工做中卻不怎麼使用,所以就忘了。工具
這裏,我準備爲對 CSS
動畫掌握不深的小夥伴補充一下相關知識。歡迎大佬們拍板。動畫
正文開始。網站
經過開發者工具能夠發現,animation
(動畫)屬性是 8 個屬性的簡寫。ui
這 8 個屬性具體含義以下:
屬性 | 描述 |
---|---|
animation-duration | 指定動畫完成一個週期所須要時間,單位秒(s)或毫秒(ms),默認是 0。 |
animation-timing-function | 指定動畫計時函數,即動畫的速度曲線,默認是 "ease"。 |
animation-delay | 指定動畫延遲時間,即動畫什麼時候開始,默認是 0。 |
animation-iteration-count | 指定動畫播放的次數,默認是 1。 |
animation-direction | 指定動畫播放的方向。默認是 normal。 |
animation-fill-mode | 指定動畫填充模式。默認是 none。 |
animation-play-state | 指定動畫播放狀態,正在運行或暫停。默認是 running。 |
animation-name | 指定 @keyframes 動畫的名稱。 |
下面咱們一個個仔細說明,各個動畫屬性都是用來作什麼的,以及須要注意的地方。
CSS
動畫,也稱關鍵幀動畫。經過 @keyframes
來定義關鍵幀。
幀的概念,想必你們很清楚,好比電影就是一幀幀圖片在播放,利用圖像在人腦中短期停留來造成動態效果。CSS
動畫也是利用這個原理。不過開發者不須要給出每一幀的定義。只須要定義一些關鍵的幀便可。由於其他的幀,瀏覽器會根據計時函數插值計算出來。
好比咱們一個 div
旋轉一圈,只須要定義開始和結束兩幀便可:
@keyframes rotate{
from{
transform: rotate(0deg);
}
to{
transform: rotate(360deg);
}
}
複製代碼
其中,rotate
是我給這個動畫起的名字,from
表示最開始的那一幀,to
表示結束時的那一幀。
準確地說,CSS
動畫用百分比來刻畫一個動畫週期,from
實際上是 0%
的別稱,to
是 100%
的別稱。所以關鍵幀 rotate
等價於:
@keyframes rotate{
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
複製代碼
定義好了關鍵幀後,下來就能夠直接用它了:
animation: rotate 2s;
複製代碼
或者:
animation-name: rotate;
animation-duration: 2s;
複製代碼
經過 animation-name
來指定動畫使用的關鍵幀,這個是必須的。用 JS
來理解的話,至關於:只有變量聲明是不行的,還須要使用。
另外上述代碼還指定了動畫運行的時間 animation-duration
爲 2s
。最後運行效果以下:
動圖的效果不是太明顯,方塊在旋轉時,不是勻速的。由於此時刻畫動畫速度的屬性 animation-timing-function
默認值是 ease
,即先快後慢。
下面動圖演示了計時函數屬性一些值的情形:
animation-timing-function
常見值有:linear
、ease
、ease-in
、ease-out
、ease-in-out
。這些值其實都是 cubic-bezier(n,n,n,n)
的特例。它們被稱爲貝塞爾曲線。除了開發者工具外,《CSS揭祕》做者也寫了的一個在線調試貝塞爾曲線的網站:cubic-bezier.com。貝塞爾曲線這個知識點頗有用,canvas
裏也有相應的 API
。能夠展開的點其實比較多,這裏只是初步介紹。
須要提一下,計時函數屬性另外的一個好玩的值是 steps
函數,能夠用來實現逐幀動畫:
計時函數屬性介紹到此,後面一概使用值 linear
,即表示勻速動畫。
回到關鍵幀,咱們除了指定開頭和結束位置的關鍵幀(若是不指定 0%
和 100%
,瀏覽器會自動推斷),固然也能夠指定任意百分比的幀是什麼狀況,好比開篇例子的另外一種實現:
div{
width: 40px;
height: 40px;
border-radius: 50%;
background: #0ff;
animation: move 6s linear both;
}
@keyframes move{
0%{
transform: translate(0,0);
}
33%{
transform: translate(200px,0);
}
66%{
transform: translate(0,0);
}
100%{
transform: translate(200px,0);
}
}
複製代碼
關鍵幀代碼有冗餘,能夠進一步簡寫:
@keyframes move{
0%, 66%{
transform: translate(0,0);
}
33%,100%{
transform: translate(200px,0);
}
}
複製代碼
此時,動畫時長改爲了 6s
,動畫進行到三分之一處時,讓 div
位於 200px
,三分之二回到開始位置,結束時移動到 200px
處。
這種是比較直觀的實現方式,有不少面試者通常都會想到這種。
注意 animation: move 6s linear both;
聲明中的 both
。它是屬性 animation-fill-mode
的一個值。這個屬性容易被忽略,然而倒是 CSS
動畫比較重要的一個屬性。直譯爲動畫填充模式,具體說的是什麼事情呢?
@keyframes
只是定義了動畫過程當中每一幀的值,然而在動畫開始前和動畫結束後,元素改處於什麼狀態呢?animation-fill-mode
說的就是這個事情。除了默認值 none
外,還有另外 3 個值:
舉個例子,div
從 100px
處移動到 200px
處的關鍵幀定義爲:
@keyframes move{
0%{
transform: translate(100px,0);
}
100%{
transform: translate(200px,0);
}
}
複製代碼
設置填充模式爲 forwards
時,動畫最後停留在 200px
處:
設置動畫延遲 1s
後執行,且填充模式爲 backwards
時,能夠看到動畫在開始前是處於 100px
處,動畫結束後回到 0px
處:
最後設置填充模式爲 both
的情形:
動畫結束後,保持動畫最後一幀的狀態,這個太有用了,好比咱們能夠實現一個進度條:
div{
height: 10px;
border: 1px solid;
background: linear-gradient(#0ff,#0ff);
background-repeat: no-repeat;
background-size: 0;
animation: move 2s linear forwards;
}
@keyframes move{
100%{
background-size: 100%;
}
}
複製代碼
效果以下:
上面提到了可使用 animation-delay
設置延遲時間。不爲你們注意的是,延遲能夠爲負數。負延遲表示動畫彷彿開始前就已經運行過了那麼長時間。
拿上述進度條爲例子,原動畫用了 2s
是從 0%
加載到 100%
的。若是設置延遲爲 -1s
。這動畫會從 50%
加載到 100%
。彷彿已經運行了 1s
同樣:
CSS
動畫是能夠暫停的。屬性 animation-play-state
表示動畫播放狀態,默認值 running
表示播放, paused
表示暫停:
animation-play-state
這個屬性很是好用,它能夠與負延遲一塊兒實現特殊的效果,好比進度條插件:
目前爲止還有兩個屬性沒有介紹,一個是 animation-iteration-count
表示動畫播放次數。它很好懂,只有一點要注意,無限播放時使用 infinite
。另外一個是播放方向 animation-direction
,它的意思說指定動畫按照指定順序來播放 @keyframes
定義的關鍵幀。其值有:
示意以下:
animation
屬性以及 8 個子屬性介紹完了,另外須要說明的是它們與 background
及其各子屬性同樣,是支持多個值的,即在同一個元素上應用多個動畫,送給你們一個如意金箍棒:
<style>
div{
margin: 200px;
height: 20px;
border: 1px solid;
animation: rotate 2.5s infinite, color 2s infinite, width 3s infinite;
animation-direction: normal, normal, alternate;
}
@keyframes rotate {
100%{
transform: rotate(360deg);
}
}
@keyframes color {
20%{
background-color: #f91;
}
80% {
background-color: #0ff
}
}
@keyframes width {
0% {
width: 40%;
}
100% {
width: 70%;
}
}
複製代碼
效果以下:
本文完。