利用 CSS3 的 Animation 能夠建立動畫,在許多頁面中可以替代 Flash、JS 等,提高頁面加載速度。衆所周知,Animation 有 8 大屬性,以下所述:函數
屬性名 | 簡介 |
---|---|
animation-name | 規定須要綁定到選擇器的 keyframe 名稱 |
animation-duration | 完成動畫所花費的時間,以秒或毫秒計 |
animation-timing-function | 規定動畫的速度曲線 |
animation-delay | 動畫開始前的延遲 |
animation-iteration-count | 動畫播放次數 |
animation-direction | 規定是否應該輪流反向播放動畫 |
animation-play-state | 指定動畫是否正在運行或已暫停 |
animation-fill-mode | 當動畫不播放時(動畫完成或動畫延遲),要應用到元素的樣式 |
以上這 8 個屬性就決定了 Animation 可以實現一個什麼樣的動畫效果。 動畫
本文主要介紹 timing-function
中的steps()
函數。Animation 在執行動畫時默認以 ease
函數進行過渡,ease 會在每一個關鍵幀之間插入補間動畫,因此動畫效果是連貫的。
除了ease函數以外,linear
和cubic-bezier
(貝塞爾曲線)等過渡函數也會爲其插入補間動畫。url
但有的時候某些效果不須要補間,只須要在關鍵幀之間進行跳躍,這時就用到了steps()過渡方式。spa
steps()
是 Animation 中的一個timing-function
函數, 可以實現動畫的階躍式變化,而非兩個狀態間的線性過渡。 steps()
接收兩個參數:3d
steps ( n, [start | end] )
你們都見過很經典的菊花 loading 效果圖,其實現原理很簡單:
一張靜態圖片,而後爲其添加動畫:調試
設定在固定步數內旋轉(rotate) 360 度便可實現 loading 效果,具體實現方式以下:
<div> <img class = "loading-dot-step" src="./loading.png"> </div> ... .loading-dot-step { animation: loading 1s infinite steps(12,start); } @keyframes loading { 0% {transform: rotate(0deg);} 100% {transform: rotate(360deg);} }
靜態圖片如圖所示:code
給上面的靜態圖片添加動畫,steps 設定 12 步完成兩個關鍵幀間的動做軌跡,即從當前狀態旋轉 360 度,實現下面 gif 的動畫效果。orm
除了菊花 loading 效果,很常見的還有線性 loading,其實現方式是:
利用 timing-function
的 linear
線性過渡函數,實現圖片的連續旋轉,此時的效果在視覺上就是連續的動畫,以下圖所示:cdn
對於兩種 loading 效果圖,第一種爲 steps
方式,第二種爲線性過渡
方式。
二者實現原理相似:blog
均在兩個關鍵幀之間將圖片從當前狀態旋轉至 360 度,當 timing-function 設置爲 linear 時,從 0% 到 100% 的狀態變化爲勻速線性變化;
當動做設定爲 steps 時,將從 0 度旋轉至 360 度的整個動畫分爲 12 步執行完,且每步之間是跳躍的,所以出現了經典的菊花 loading 效果。
steps 的執行點 start 和 end 是許多人存在疑惑的地方,誤用 start 和 end 可能會出現和理想狀況下不一致的動畫效果,許多人分不清二者的區別在哪裏,下面以幾個簡單的 demo 來輔助理解這兩個屬性值的區別。
steps()
可簡化出 step-start
和 step-end
這兩個關鍵字。
<p>一、steps(1, start)</p> <div class="a box"></div> <p>二、steps(1, end)</p> <div class="b box"></div> ... .a{ animation:changeColor 4s infinite steps(1, start); } .b{ animation:changeColor 4s infinite steps(1, end); } @keyframes changeColor{ 0%{ background-color: red; } 100%{ background-color: blue; } }
上述代碼顯示效果以下圖所示:
一、steps(1, start)
二、steps(1, end)
代碼可見,二者設定的均爲 1 步執行完動畫,實現將 div 的顏色從紅色變爲藍色
,可是咱們看到的結果倒是不一樣的,這就是因爲 start
和 end
兩個屬性的執行點不一樣形成的結果差別。
規範文檔中給出了關於 steps()
的函數圖,以下圖所示:
對比 steps 函數中的 start 和 end 兩個執行點,由上圖中步數爲 1 的兩圖可見:
一樣,當步數等於 3 時,肉眼可見的 start 的執行點爲第一步執行結束的位置,end 的執行點則爲第一步還沒有開始的位置 。因爲動畫執行的步數相同但起點不一樣,所以動畫的結束點也不相同,設置爲 start 的狀況下,結束點爲動畫結束的最後一步的狀態,而 end 爲結束前一步的狀態。
爲了更加直觀地展現二者執行的開始點和結束點的區別,本文以橫向座標圖的方式對執行過程進行示意:
如今能夠解釋上述 demo 中兩個 div 顏色顯示不同的緣由了,對於 steps 屬性值爲 start 的 a-box,進入畫面時動畫的第一階段已經完成,所以咱們不會看到紅色,直接顯示藍色;對於 steps 屬性值爲 end 的 b-box,動畫保持第一幀的狀態直到結束,所以始終顯示爲紅色。
並不是全部的動畫都是連續的,對於某些非連續變化的效果就須要用到 steps 來實現。 例如鐘錶秒針階躍式的轉動,或者在動畫中模仿人物或動物的腳印行走效果,再或者利用雪碧圖實現人物跑動的效果等等。下面詳細介紹一下人物跑動效果的實現方式。
人物奔跑 demo
<div class="person"></div> ... .person { background: url('person.jpg') no-repeat; background-size: 800%; // 動畫名稱 持續時間 運動曲線(steps()分爲幾步)循環次數 animation: personBlast .8s steps(7) infinite; } @keyframes personBlast { 0% { background-position: left; } 100% { background-position: right; } }
其中 person.jpg 爲人物動做分割的雪碧圖:
本文奔跑動做實現方式爲將原始雪碧圖進行按圖形幀數的倍數放大
,而後設定steps 爲雪碧圖的幀數減 1(8 幀分爲 7 步執行完),關鍵幀的動做爲從 (from) 雪碧圖左側階躍式跳躍到(to)右側,最終實現下面的跑動效果:
【 注:此奔跑效果的實現方式不盡相同,此處只是其中一種,這樣作是爲了讓你們更好的理解 steps 的應用場景,還有其餘更友好的實現方式歡迎你們一塊兒交流 】
對於 Animation 的 timing-function 有一個須要引發注意的點,即:
timing-function 的執行位置爲兩個關鍵幀之間,而非整個動畫
此處的 timing-function 指的是本文所講的 steps 函數以及 linear、ease、cubic-bezier 等函數。
這裏仍是經過一個簡單的 demo 來了解這個點。首先看一下下面的動畫效果:
實現代碼爲:
<div class="test test-a"></div> <div class="test test-b"></div> ... .test-a { animation: changeColorOne 1s steps(1) infinite; } .test-b { animation: changeColorTwo 1s steps(1) infinite; } @keyframes changeColorOne { 0% { background-color: red; } 100% { background-color: blue; } } @keyframes changeColorTwo { 0% { background-color: red; } 25%{ background-color: blue; } 75%{ background-color: red; } 100% { background-color: blue; }
所以:steps 並不是做用於整個動畫,而是做用於每兩個關鍵幀之間,與動畫的時長、播放次數等都無關,因此整個動畫的執行時間仍是 Animation 中設定的 1s。
Animation 時間函數中的 steps() 確實很差理解,可是一旦掌握了它會爲咱們的開發工做帶來很大的效率提高,節省不少調試時間,也能幫助咱們快速定位問題。 但願本文的講解能夠幫助你更好的理解和使用 steps()。感謝閱讀,歡迎互相交流!