2019年了,你還不會CSS動畫?

今年我面試了不少同窗,只要看到簡歷上寫「熟練掌握CSS3」的,我都會問問動畫相關知識。然而我發現:都 2019 年了,還有不少同窗不會 CSS 動畫。css

我常常愛問的一個問題是,實現以下的效果:面試

即,一個小球從向右勻速移動 200px,而後移動回來,再移動過去,最後停留在 200px 處。canvas

動圖效果以下:
瀏覽器

就是需求這麼簡單的一個動畫,然而絕大多數人卻不能答對。app

不賣關子,個人答案是:函數

div{
  width40px;
  height40px;
  border-radius50%;
  background#0ff;
  animation: move 2s linear 3 alternate both;
}
@keyframes move{
  0%{
    transformtranslate(0,0);
  }
  100%{
    transformtranslate(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{
    transformrotate(0deg);
  }
  to{
    transformrotate(360deg);
  }
}
複製代碼

其中,rotate 是我給這個動畫起的名字,from 表示最開始的那一幀,to 表示結束時的那一幀。

準確地說,CSS 動畫用百分比來刻畫一個動畫週期,from 實際上是 0% 的別稱,to100% 的別稱。所以關鍵幀 rotate 等價於:

@keyframes rotate{
  0%{
    transformrotate(0deg);
  }
  100%{
    transformrotate(360deg);
  }
}
複製代碼

定義好了關鍵幀後,下來就能夠直接用它了:

animationrotate 2s;
複製代碼

或者:

animation-namerotate;
animation-duration: 2s;
複製代碼

經過 animation-name 來指定動畫使用的關鍵幀,這個是必須的。用 JS 來理解的話,至關於:只有變量聲明是不行的,還須要使用。

另外上述代碼還指定了動畫運行的時間 animation-duration2s。最後運行效果以下:

動圖的效果不是太明顯,方塊在旋轉時,不是勻速的。由於此時刻畫動畫速度的屬性 animation-timing-function 默認值是 ease,即先快後慢。

下面動圖演示了計時函數屬性一些值的情形:

animation-timing-function 常見值有:lineareaseease-inease-outease-in-out。這些值其實都是 cubic-bezier(n,n,n,n) 的特例。它們被稱爲貝塞爾曲線。除了開發者工具外,《CSS揭祕》做者也寫了的一個在線調試貝塞爾曲線的網站:cubic-bezier.com。貝塞爾曲線這個知識點頗有用,canvas 裏也有相應的 API。能夠展開的點其實比較多,這裏只是初步介紹。

須要提一下,計時函數屬性另外的一個好玩的值是 steps 函數,能夠用來實現逐幀動畫:

計時函數屬性介紹到此,後面一概使用值 linear,即表示勻速動畫。

回到關鍵幀,咱們除了指定開頭和結束位置的關鍵幀(若是不指定 0%100%,瀏覽器會自動推斷),固然也能夠指定任意百分比的幀是什麼狀況,好比開篇例子的另外一種實現:

div{
  width40px;
  height40px;
  border-radius50%;
  background#0ff;
  animation: move 6s linear both;
}
@keyframes move{
  0%{
    transformtranslate(0,0);
  }
  33%{
    transformtranslate(200px,0);
  }
  66%{
    transformtranslate(0,0);
  }
  100%{
    transformtranslate(200px,0);
  }
}
複製代碼

關鍵幀代碼有冗餘,能夠進一步簡寫:

@keyframes move{
  0%, 66%{
    transformtranslate(0,0);
  }
  33%,100%{
    transformtranslate(200px,0);
  }
}
複製代碼

此時,動畫時長改爲了 6s,動畫進行到三分之一處時,讓 div 位於 200px,三分之二回到開始位置,結束時移動到 200px 處。

這種是比較直觀的實現方式,有不少面試者通常都會想到這種。

注意 animation: move 6s linear both; 聲明中的 both。它是屬性 animation-fill-mode 的一個值。這個屬性容易被忽略,然而倒是 CSS 動畫比較重要的一個屬性。直譯爲動畫填充模式,具體說的是什麼事情呢?

@keyframes 只是定義了動畫過程當中每一幀的值,然而在動畫開始前和動畫結束後,元素改處於什麼狀態呢?animation-fill-mode 說的就是這個事情。除了默認值 none 外,還有另外 3 個值:

  • forwards,表示,動畫完成後,元素狀態保持爲最後一幀的狀態。
  • backwards,表示,有動畫延遲時,動畫開始前,元素狀態保持爲第一幀的狀態。
  • both,表示上述兩者效果都有。

舉個例子,div100px 處移動到 200px 處的關鍵幀定義爲:

@keyframes move{
  0%{
    transformtranslate(100px,0);
  }
  100%{
    transformtranslate(200px,0);
  }
}
複製代碼

設置填充模式爲 forwards 時,動畫最後停留在 200px 處:

設置動畫延遲 1s 後執行,且填充模式爲 backwards 時,能夠看到動畫在開始前是處於 100px 處,動畫結束後回到 0px 處:

最後設置填充模式爲 both 的情形:

動畫結束後,保持動畫最後一幀的狀態,這個太有用了,好比咱們能夠實現一個進度條:

div{
  height10px;
  border1px solid;
  backgroundlinear-gradient(#0ff,#0ff);
  background-repeat: no-repeat;
  background-size0;
  animation: move 2s linear forwards;
}
@keyframes move{
  100%{
    background-size100%;
  }
}
複製代碼

效果以下:

上面提到了可使用 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 定義的關鍵幀。其值有:

  • normal 默認值。
  • reverse 表示動畫反向播放。
  • alternate 表示正向和反向交叉進行。
  • alternate-reverse 表示反向和正向交叉進行。

示意以下:

animation 屬性以及 8 個子屬性介紹完了,另外須要說明的是它們與 background 及其各子屬性同樣,是支持多個值的,即在同一個元素上應用多個動畫,送給你們一個如意金箍棒:

<style>
div{
  margin200px;
  height20px;
  border1px solid;
  animation: rotate 2.5s infinite, color 2s infinite, width 3s infinite;
  animation-direction: normal, normal, alternate;
}
@keyframes rotate { 
  100%{ 
    transformrotate(360deg); 
  } 
}
@keyframes color { 
  20%{ 
    background-color#f91
  } 
  80% {
    background-color#0ff
  }
}
@keyframes width { 
  0% {
    width40%;
  }
  100% {
    width70%;
  }
}
複製代碼

效果以下:

本文完。

相關文章
相關標籤/搜索