過段時間要幫女孩作一些計算機視覺的東西,因此研究下動畫這一塊。前端建立動畫的方式有三種,分別是 定時器, requestAnimationFrame 以及 CSS3 Animation,而 requestAnimationFrame 的出現基本秒殺了定時器。雖然 Animation 暫沒法處理如三次方緩動、指數衰減正弦曲線緩動等須要高級數學運算的動畫(貌似 CSS3 要支持三角函數了),但在絕大多數狀況下依舊能夠作出很是優秀的動畫效果,這裏對 Animation 各屬性作個總結。css
目前 animation 有下面 9 種屬性,其中第一個是後面屬性的簡寫形式。html
屬性 | 描述 |
---|---|
animation | 下面各屬性的簡寫(除了 animation-play-state) |
animation-name | 指定 @keyframes 動畫的名稱 |
animation-duration | 動畫完成一個週期的時間,默認爲 0s |
animation-timing-function | 動畫運行的'節奏',默認是 ease |
animation-delay | 動畫開始播放的延遲時間,默認是 0 |
animation-iteration-count | 動畫播放的次數,默認是 1 |
animation-direction | 規定動畫是否在下一個週期逆向播放 |
animation-fill-mode | 規定動畫的填充模式 |
animation-play-state | 控制動畫的運行或暫停,默認是 running |
該屬性用於指定 @keyframes 動畫的名稱。定義關鍵幀須要使用 @keyframes
規則。樣式塊語句中可使用 from...to 結構,也可使用百分比來定義。前端
以下面這段代碼,它在動畫開始運行時將元素放大 1.1 倍,在動畫運行到一半時將元素縮小爲 0.8 倍,在動畫結束時將元素再放大爲 1.1 倍,配合上後面要講到的 infinite 和貝塞爾曲線,就能夠模擬出不錯的心跳動畫效果。css3
.heart {
animation: heartbeat cubic-bezier(0.2, 0.73, 0.71, 0.44) infinite;
}
@keyframes heartbeat {
0% {
transform: scale(1.1);
}
50% {
transform: scale(0.8);
}
100% {
transform: scale(1.1);
}
}
複製代碼
該屬性定義一個動畫週期的時長。git
默認值爲 0s,表示無動畫github
單位爲秒或者毫秒,無單位值無效wordpress
該屬性用於定義動畫的'節奏',默認值爲 ease.函數
屬性值 | 描述 |
---|---|
ease | 緩慢開始,緩慢結束 |
ease-in | 先慢後快 |
ease-out | 先快後慢 |
ease-in-out | 以慢速開始和結束的過渡效果 |
linear | 平滑效果 |
step-start | 步進,忽略第一幀 |
step-end | 步進,忽略最後一幀 |
step-middle | 步進,從第一幀到最後一幀 |
不論是在 Animation 仍是 Transition 裏,前 5 個應該很常見,咱們能夠直接在 Chrome Dev 中查看具體的函數圖像(其實這五個就是貝塞爾曲線的幾種特殊形式)。post
step-start, step-end 和 step-middle 表示步進動畫。動畫
其中 step-start 會忽略相應 @keyframs 規則的第一幀,而 step-end 會忽略最後一幀, step-middle 在一個週期內會從第一幀一直步進到最後一幀。
看下面這個例子,當使用 step-start
時,元素的初始狀態就是 1.2 倍(對應着 25%),一個週期內步進執行 25% -> 50% -> 75% -> 100%
當使用 step-end
時,元素的初始狀態是 1.1 倍(對應着 0%),一個週期內步進執行 0% -> 25% -> 50% -> 75%
當使用 step-middle
時,元素的初始狀態就是元素的初始狀態,一個週期內步進執行 0% -> 25% -> 50% -> 75% -> 100%
@keyframes someEffect {
0% {
transform: scale(1.1);
}
25% {
transform: scale(1.2);
}
50% {
transform: scale(1.3);
}
75% {
transform: scale(1.4);
}
100% {
transform: scale(1.5);
}
}
複製代碼
此外該屬性還有三個內置函數,分別是 cubic-bezier(), steps() 以及 frames()。
這裏簡單談一談 steps()。若是你用過 Twitter,你應該知道它的點贊效果很酷,能夠看下圖。這個效果徹底能夠用 steps() 模擬出來,個人博客中點贊模塊也有這個效果,不過是用的 box-shadow,你能夠看源碼 Like Component
首先你要下載下面這張圖片,能夠看到它是一張 未點贊狀態 -> 生成禮花 -> 禮花消失 -> 點贊狀態 的雪碧圖。
在初始化時,咱們經過 background-position: left
和 background-size: 2900%
將初始背景定位到上圖中第一個灰色的 icon.
接着咱們建立一個 @keyframes,用於在一個動畫週期內將上面的圖片從左到右一次性走完。
爲了每一幀都會「跳」到下一個 icon,而不是平滑的移動。咱們使用 steps() 函數,由於共有 29 張小 icon,其中默認是第一個,因此傳遞參數 28.
在點擊背景圖片時,將 is_animating
添加到 heart 元素上,便可實現點贊禮花效果。
<div class="heart"></div>
複製代碼
.heart {
cursor: pointer;
height: 50px;
width: 50px;
background-image: url('heart-locus.png');
background-position: left;
background-repeat: no-repeat;
background-size: 2900%;
}
.is_animating {
animation-name: heart-burst;
animation-duration: 800ms;
animation-timing-function: steps(28);
animation-iteration-count: 1;
}
@keyframes heart-burst {
from {
background-position: left;
}
to {
background-position: right;
}
}
複製代碼
const heartDOM = document.querySelector('.heart');
heartDOM.addEventListener('click', function() {
this.classList.toggle('is_animating');
});
heartDOM.addEventListener('animationend', function() {
this.classList.toggle('is_animating');
});
複製代碼
該屬性用於將動畫延遲執行,默認值爲 0s。當該屬性的屬性值爲負值會出現一些好玩的事情,咱們直接看 MDN 上的定義。
定義一個負值會讓動畫當即開始。可是動畫會從它的動畫序列中某位置開始。例如,若是設定值爲-1s,動畫會從它的動畫序列的第 1 秒位置處當即開始。 若是爲動畫延遲指定了一個負值,但起始值是隱藏的,則從動畫應用於元素的那一刻起就獲取起始值。
咱們看下面這個例子:
.cube {
margin-bottom: 10px;
width: 100px;
height: 100px;
background: #ccc;
animation: colorChange 10s linear;
}
.has-delay {
animation-delay: 2s;
}
.has-ng-delay {
animation-delay: -2s;
}
@keyframes colorChange {
20% {
background-color: #f8e81c;
}
40% {
background-color: #d0011b;
}
60% {
background-color: #7ed321;
}
80% {
background-color: #509ce3;
}
100% {
background-color: #ccc;
}
}
複製代碼
html 結構以下:
<div class="cube"></div>
<div class="cube has-ng-delay"></div>
<div class="cube has-delay"></div>
複製代碼
這個例子中,咱們將 cube 的動畫總時長設爲 10s,且初始顏色都是灰色。不一樣的是,第一個 cube 正常執行,第二個 cube "延遲" -2s 執行,第三個 cube 延遲 2s 執行。
根據下面這張圖能夠看出,第二個 cube 雖然是負數,但從動畫一開始就會執行,只不過它是從第二幀開始的。
這是由於定義在 @keyframes 中的動畫須要執行 animation-time 時間長度。animation-delay 爲正數的時候,動畫就要要延遲開始,animation-time 都尚未開始計算,正數的 delay 不會被計算到 animation-time 中,所以咱們看到的動畫就是從第一幀開始的;animation-delay 爲負數的時候,意味着動畫是提早開始的,animation-time 已經開始計算了,負數的 delay 是被算入 animation-time 中的,因此咱們看到的動畫是從某一幀開始的。
因此咱們能夠嘗試寫個 loading 組件出來。源碼貼在下面。
.loader-container {
width: 210px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-row-gap: 10px;
grid-column-gap: 10px;
}
.cube {
width: 100px;
height: 100px;
background: #ccc;
animation: colorChange 5s linear infinite;
}
.delay-neg-1 {
animation-delay: -1s;
}
.delay-neg-2 {
animation-delay: -2s;
}
.delay-neg-3 {
animation-delay: -3s;
}
.delay-neg-4 {
animation-delay: -4s;
}
複製代碼
下面是 HTML
<div class="loading-container">
<div class="cube delay-neg-1"></div>
<div class="cube delay-neg-2"></div>
<div class="cube delay-neg-3"></div>
<div class="cube delay-neg-4"></div>
</div>
複製代碼
該屬性定義循環播放動畫的次數,默認值爲 1
不能夠爲負數
infinite 表示無限循環
能夠爲小數,好比 0.5 表明播放動畫的一半即結束
該屬性表示動畫是否反向播放,共有 4 個值:
normal: 每次從 @keyframes 0% 執行到 100%,一個週期結束後當即回到 0% 的位置
alternate: 假設 animation-iteration-count: infinite
,從 @keyframes 0% 執行到 100%後,再從 100% 的位置 回到 0%,周而復始
reverse: 每次從 @keyframes 100% 執行到 0%,,一個週期結束後當即回到 100% 的位置
alternate-reverse: 假設 animation-iteration-count: infinite
,從 @keyframes 100% 執行到 0%後,再從 0% 的位置 回到 100%,周而復始
用於設定動畫時間外的屬性,也就是說一個動畫週期開始以前或結束以後,元素的狀態應該是什麼樣的。該屬性有四個屬性值,分別是 none, forwards, backwards, both.
none 是默認值,表示動畫播放完成後,恢復到初始的狀態。
forwards 表示動畫播放完成後,保持 @keyframes 裏最後一幀的樣式。
backwards 表示開始播放動畫以前,元素的樣式將設置爲動畫第一幀的樣式
both 至關於同時配置了 forwards 和 backwards。也就是說,動畫開始前,元素樣式將設置爲動畫第一幀的樣式;而在動畫線束狀態,元素樣式將設置爲動畫最後一幀樣式。
該屬性用於讓一個動畫的暫停與啓動,有兩個屬性值,分別是 running 和 pause,當設置爲 pause 時,動畫會當即會停在當前位置,當取消暫停後會在停住的位置繼續執行,而不會回到原點(或終點)從新執行。
最後說一下 animation 屬性,它是上述屬性的簡寫形式,animation 屬性暫時尚未收錄 animation-play-state
,如若使用須要單獨來寫,語法以下。
animation: name duration timing-function delay iteration-count direction fill-mode;
複製代碼
上面咱們看到了每一個屬性均可以添加多個屬性值,他們之間用逗號隔開,其實就是給一個元素添加多個動畫。
複習 animation-delay 負值以及 delay 正值在 iOS 上的坑
前端 Talkking CSS 系列 —— 一步一步帶你認識 animation 動畫效果