創建動畫的 API#
在 CSS 中創建動畫主要依賴於以下幾個關鍵的 API:
-
@keyframes
規則- 用於定義動畫的中間步驟(關鍵幀)。在
@keyframes
規則中,可以設定在動畫過程中某個或某些時刻元素的樣式。
@keyframes example { from {background-color: red;} to {background-color: yellow;} }
或者使用百分比來指定多個關鍵幀:
@keyframes example { 0% {background-color: red;} 50% {background-color: blue;} 100% {background-color: yellow;} }
@keyframes
規則什麼時候觸發?- 當元素綁定了
animation-name
屬性,並且動畫開始時,@keyframes
規則中定義的關鍵幀將按照指定的時間和速度曲線進行執行。 - 例如,上面的
example
動畫在animation-name
屬性中綁定到元素後,將按照animation-duration
和animation-timing-function
屬性的設置進行執行。
- 用於定義動畫的中間步驟(關鍵幀)。在
-
animation-name
屬性- 指定需要綁定到選擇器的
@keyframes
名稱。
.element { animation-name: example; }
- 指定需要綁定到選擇器的
-
animation-duration
屬性- 定義動畫完成一個週期所花費的時間,例如秒或毫秒。
.element { animation-duration: 2s; }
-
animation-timing-function
屬性- 定義動畫的速度曲線,例如
linear
,ease
,ease-in
,ease-out
,ease-in-out
, 或者cubic-bezier
函數。
.element { animation-timing-function: ease-in-out; }
在 CSS 動畫中,可以通過指定動畫的速度曲線來控制動畫的變化速度。以下是一些常用的速度曲線:
-
linear
- 動畫從頭到尾的速度是相同的。這意味著動畫以恆定速度平滑地進行,沒有加速或減速的過程。
-
ease
- 預設的速度曲線。動畫以低速開始,然後加速,最後再減速。這使得動畫看起來更自然,因為它模擬了現實世界中物體的運動狀態。
-
ease-in
- 動畫以低速開始,隨著動畫的進行,速度逐漸增加,直到結束。這種曲線適用於需要強調動作開始階段的場景。
-
ease-out
- 動畫以全速開始,然後逐漸減速直到停止。這種曲線適用於需要強調動作結束階段的場景。
-
ease-in-out
- 動畫以低速開始和結束,中間部分以較快的速度運動。這種速度曲線是
ease-in
和ease-out
的結合,適用於需要平滑過渡的場景。
- 動畫以低速開始和結束,中間部分以較快的速度運動。這種速度曲線是
-
cubic-bezier(n,n,n,n)
- 允許你自定義一個速度曲線。
cubic-bezier
函數接受四個參數,這些參數定義了一個三次貝塞爾曲線,可以精確控制動畫的加速和減速過程。CSS 提供了一個cubic-bezier
工具,幫助你可視化和調整這四個參數。
ease-n. 容易;舒適,自在
v. 減輕,緩和,放鬆;緩緩移動;使容易;降低;使離職;熟悉
- 允許你自定義一個速度曲線。
- 定義動畫的速度曲線,例如
-
animation-delay
屬性- 設置動畫在啟動前的延遲時間。
.element { animation-delay: 1s; }
-
animation-iteration-count
屬性- 定義動畫應該播放的次數,可以是數字或者
infinite
表示無限次重複。
.element { animation-iteration-count: infinite; }
- 定義動畫應該播放的次數,可以是數字或者
-
animation-direction
屬性- 指定動畫是否應該輪流反向播放。常見值有
normal
,reverse
,alternate
,alternate-reverse
。
.element { animation-direction: alternate; }
- 指定動畫是否應該輪流反向播放。常見值有
-
animation-fill-mode
屬性- 指定在動畫執行之前和之後如何為目標元素應用樣式。例如,
forwards
保留最後一幀的樣式。
.element { animation-fill-mode: forwards; }
animation-fill-mode
屬性在 CSS 動畫中用來指定一個動畫在執行之前和之後如何將樣式應用到其目標元素上。簡而言之,它決定了動畫執行前後元素的樣式表現。animation-fill-mode
屬性接受以下幾個值:none
- 預設值。不改變預設行為。動畫不會將任何樣式應用於目標元素,動畫結束後元素會回到動畫未執行時的狀態。
forwards
- 動畫完成後,元素將保留由動畫的最後一個關鍵幀計算值決定的樣式。即動畫結束後元素會保留動畫結束時的樣式。
backwards
- 動畫將在應用於元素的那一刻立即應用第一關鍵幀的樣式,即使動畫延遲開始。這意味著元素會立即獲得動畫初始狀態的樣式,直到動畫真正開始。
both
- 動畫遵循
forwards
和backwards
的規則,意味著動畫會在延遲期間應用第一關鍵幀的樣式,並在動畫結束後保留最後一個關鍵幀的樣式。
- 動畫遵循
例如,如果你有一個淡出動畫,你可能希望動畫結束後元素保持透明
- 指定在動畫執行之前和之後如何為目標元素應用樣式。例如,
-
animation
簡寫屬性- 可以使用
animation
簡寫屬性同時設置所有動畫屬性。
.element { animation: example 2s infinite ease-in-out; }
- 可以使用
-
animation-play-state
屬性- 控制動畫的播放狀態。可以設置為
paused
暫停動畫,或者running
繼續播放動畫。
.element { animation-play-state: paused; }
- 控制動畫的播放狀態。可以設置為
-
使用 CSS 變量控制動畫
- CSS 變量(自定義屬性)可以與動畫結合使用,為動畫提供動態值或實現主題定製。
:root { --animation-duration: 2s; } .element { animation-duration: var(--animation-duration); }
-
使用
@media
查詢和動畫- 可以結合媒體查詢來應用不同的動畫效果,使動畫響應不同的螢幕尺寸或設備特性。
@media (max-width: 600px) { .element { animation-name: exampleSmallScreen; } }
-
will-change
屬性- 提前告知瀏覽器元素將要進行的變化,以優化性能。雖然不是直接控制動畫的屬性,但適當使用可以提高動畫的流暢度。
.element { will-change: transform, opacity; }
-
利用 CSS 動畫實現性能優化
- 在可能的情況下,使用 transform 和 opacity 動畫,因為它們可以通過硬體加速,提高動畫的性能。
-
動畫事件
- 雖然 CSS 本身不直接提供事件監聽機制,但在 JavaScript 中,可以監聽動畫相關的事件,如
animationstart
,animationend
, 和animationiteration
,以在動畫的不同階段執行腳本。
document.querySelector('.element').addEventListener('animationend', function() { console.log('動畫結束'); });
- 雖然 CSS 本身不直接提供事件監聽機制,但在 JavaScript 中,可以監聽動畫相關的事件,如
動畫 API 的實踐#
1. keyframes 的使用#
.button {
cursor: pointer;
animation-duration: 3ms;
}
@keyframes button {
0% {
background-color: aqua;
}
100% {
background-color: bisque;
}
}
問題:它無法觸發,動畫一般何時觸發?
.button {
cursor: pointer;
animation-duration: 3s;
animation-name: bgcolor;
animation-delay: 0s;
animation-timing-function: ease-in;
background-color: aqua;
animation-fill-mode: both;
animation-iteration-count: infinite;
}
@keyframes bgcolor {
0% {
background-color: rgb(0, 140, 140);
}
100% {
background-color: rgb(208, 127, 29);
}
}
- animation-name 屬性就是將 keyframes 的名字賦值給它,這樣就可以觸發動畫了。然後它是預設第一次加載的時候就會觸發一次的。如果你綁定上。
- animation-duration 屬性是表示動畫持續時間;
- animation-delay 屬性是表示動畫延遲時間;
- animation-timing-function 是動畫時間函數,就是這個動畫它是以什麼函數執行的;linear,ease,ease-in,ease-in-out 等。而 ease 就是輕鬆,減輕的意思,ease-in 就是慢慢進。
- animation-iteration-count 是動畫的次數,iteration 就是迭代重複的意思,count 就是次數的意思。所以這個屬性就是表示動畫的次數。然後它設置的參數可以是 1,2,3,4,5... 也可以是 infinite,表示無限次重複。
- animation-play-state 是動畫的播放狀態,paused 就是暫停的意思,running 就是運行的意思。
- animation-fill-mode 是動畫的填充模式,forwards 就是向前的意思,在這裡是應用最後一幀的設置,backwards 就是向後的意思在這裡是應用第一幀的設置,一般這個第一幀是它原來的設置而不是動畫幀的第一個 0%,both 就是兩者都有的意思,這裡差不多和 forwards 相似。
2. 實現一個 hover 屬性#
- keyframers 懸停動畫的實現
.button {
cursor: pointer;
background-color: antiquewhite;
}
.button :hover {
animation-name: bgcolor;
animation-duration: 3s;
background-color: antiquewhite;
}
@keyframes bgcolor {
0% {
background-color: rgb(0, 140, 140);
}
100% {
background-color: rgb(208, 127, 29);
}
}
- 問題:為什麼懸停動畫沒有實現?
- 解決:將 button 改為.button,因為問題出在
.button :hover
選擇器上。在 CSS 選擇器中,.button :hover
表示選擇.button
內部的任何元素在懸停時的狀態,而不是.button
本身在懸停時的狀態。這是因為.button
和:hover
之間有一個空格,這代表了一個後代選擇器,意味著它將選擇.button
的子元素的懸停狀態,而不是.button
本身。
.button {
cursor: pointer;
background-color: antiquewhite;
}
.button:hover {
animation-name: bgcolor;
animation-duration: 3s;
background-color: antiquewhite;
animation-iteration-count: infinite;
}
@keyframes bgcolor {
0% {
background-color: rgb(0, 140, 140);
}
50% {
background-color: rgb(208, 127, 29);
}
100% {
background-color: rgb(0, 140, 140);
}
}
3. 實現一個點擊事件#
為什麼我點擊後沒有反饋?
.button {
cursor: pointer;
background-color: antiquewhite;
}
.button:checked {
animation-name: bgcolor;
animation-duration: 3s;
background-color: antiquewhite;
animation-iteration-count: infinite;
}
@keyframes bgcolor {
0% {
background-color: rgb(0, 140, 140);
}
50% {
background-color: rgb(208, 127, 29);
}
100% {
background-color: rgb(0, 140, 140);
}
}
問題在於使用了 .button:checked
選擇器,這個選擇器通常用於表單元素(如複選框、單選按鈕等)的選中狀態,而不是用於常規的按鈕元素。如果你的 .button
是一個 <button>
或 <div>
元素,:checked
偽類選擇器是不適用的,因此點擊時不會有任何效果。
如果你想在點擊按鈕後觸發動畫,可以考慮以下幾種方法:
- 使用 JavaScript 在點擊事件發生時添加一個類,然後通過這個類來觸發動畫。
- 如果是希望有點擊(或觸摸)的即時反饋,可以考慮使用
:active
偽類。但請注意,:active
狀態僅在元素被激活(即鼠標按下期間)時生效,一旦鼠標松開,元素就會立刻回到正常狀態。 - 對於能夠切換狀態的按鈕(如開關按鈕),可以使用隱藏的複選框(checkbox)和標籤(label)來實現。用戶點擊標籤時會改變複選框的選中狀態,從而通過複選框的
:checked
偽類來控制動畫。
改為 active 之後是激活狀態,但是松開鼠標就會回到原來的狀態。也就是說你鼠標一直按著的時候它是執行動畫的,松開就不執行了。
這不應該是點擊事件,應該叫:按住事件。
那如何實現點擊事件動畫呢?
.button {
cursor: pointer;
background-color: antiquewhite;
}
.animate {
animation-name: bgcolor;
animation-duration: 3s;
animation-iteration-count: infinite;
}
@keyframes bgcolor {
0% {
background-color: rgb(0, 140, 140);
}
50% {
background-color: rgb(208, 127, 29);
}
100% {
background-color: rgb(0, 140, 140);
}
}
document.getElementById('animatedButton').addEventListener('click', function() {
this.classList.add('animate');
});
4. 實現其他動畫效果,旋轉,放大縮小,移動等#
CSS 的transform
屬性允許你對元素進行移動、縮放、旋轉、傾斜等變形操作。以下是一些常用的transform
函數:
-
平移(Translate):
translate(x, y)
:沿 X 軸和 Y 軸移動元素。translateX(x)
:只沿 X 軸移動元素。translateY(y)
:只沿 Y 軸移動元素。
.translate { transform: translate(50px, 100px); /* 向右移動50px,向下移動100px */ }
-
縮放(Scale):
scale(x, y)
:沿 X 軸和 Y 軸縮放元素。scaleX(x)
:只沿 X 軸縮放元素。scaleY(y)
:只沿 Y 軸縮放元素。
.scale { transform: scale(2, 3); /* 寬度放大2倍,高度放大3倍 */ }
-
旋轉(Rotate):
rotate(angle)
:旋轉元素,angle
是旋轉角度,單位可以是deg
(度)、rad
(弧度)等。
.rotate { transform: rotate(45deg); /* 順時針旋轉45度 */ }
-
傾斜(Skew):
skew(x-angle, y-angle)
:沿 X 軸和 Y 軸傾斜元素。skewX(angle)
:只沿 X 軸傾斜元素。skewY(angle)
:只沿 Y 軸傾斜元素。
.skew { transform: skew(30deg, 20deg); /* 沿X軸傾斜30度,沿Y軸傾斜20度 */ }
-
組合使用:
transform
屬性可以組合使用多個變形函數,按照指定的順序應用於元素。
.combine { transform: rotate(30deg) translate(100px, 50px) scale(1.5); }
這個例子中,
.combine
類的元素首先被旋轉 30 度,然後沿 X 軸和 Y 軸移動,最後整體放大 1.5 倍。 -
matrix
變換在 CSS 中是一個非常強大的變換工具,它可以通過一個 6 值的矩陣來組合所有的 2D 變換效果(平移、旋轉、縮放、傾斜)。這個矩陣是這樣的:scaleX()
和scaleY()
分別代表沿 X 軸和 Y 軸的縮放比例。skewX()
和skewY()
分別代表沿 X 軸和 Y 軸的傾斜角度。translateX()
和translateY()
分別代表沿 X 軸和 Y 軸的平移距離。matrix(scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY())
使用matrix
變換可以實現包括平移、縮放、旋轉、傾斜在內的所有 2D 變換效果,但它不直觀,需要一定的數學知識來構造合適的矩陣值。
但是,要注意的是,matrix
變換本身只適用於 2D 變換,對於 3D 變換(如在 Z 軸的平移或旋轉),則需要使用matrix3d
或其他 3D 變換相關的函數(如translateZ()
,rotateX()
,rotateY()
,rotateZ()
,perspective()
等)。因此,如果你的問題是詢問matrix
是否可以處理 3D 變換,那麼答案是不能。對於 3D 變換,你應該使用matrix3d
或者組合使用其他 3D 變換函數。
使用transform
屬性可以在不影響頁面佈局的情況下對元素進行視覺上的變形,是實現複雜動畫和佈局效果的強大工具。此外,transform
通常配合transition
或animation
屬性一起使用,以實現平滑的過渡效果。
。
.button {
cursor: pointer;
background-color: antiquewhite;
}
.button:active {
animation-name: bgcolor;
animation-duration: 3s;
background-color: antiquewhite;
animation-iteration-count: infinite;
}
.button:hover {
animation-name: aaa;
animation-duration: 3s;
background-color: antiquewhite;
animation-iteration-count: infinite;
}
@keyframes bgcolor {
form {
transform: rotate(32deg);
}
to {
transform: rotate(90deg);
}
}
@keyframes aaa2 {
form {
transform: scale(1);
}
to {
transform: scale(2);
}
}
@keyframes aa21a {
form {
transform: skew(2deg);
}
to {
transform: skew(60deg);
}
}
@keyframes aaa {
form {
transform: translate(0px, 0px);
}
to {
transform: translate(0px, 250px);
}
}
5. 漸變過渡動畫效果#
- transition 實現漸變動畫
.button {
width: 20px;
cursor: pointer;
transform: none;
transition-property: transform width;
transition-duration: 2s;
background-color: antiquewhite;
}
.button:hover {
width: 230px;
transform: rotate(49deg);
}
- transform 轉變動畫
.button {
cursor: pointer;
transform: none;
transition: 2s;
background-color: antiquewhite;
}
.button:hover {
transform: rotate(49deg);
}
它們本質上都是通過 transition 實現的漸變動畫。transform 也是 css 的屬性一部分而已。
6. 構造@keyframes
動畫:#
- 使用 JavaScript 構造一個完整的
@keyframes
動畫,並將其插入到文檔的<style>
標籤中。 - 示例:
var duration = '2s'; var fromPosition = '-100%'; var toPosition = '0'; var styleSheet = document.createElement('style'); styleSheet.type = 'text/css'; styleSheet.innerHTML = `@keyframes dynamicSlideIn { from { transform: translateX(${fromPosition}); } to { transform: translateX(${toPosition}); } }`; document.head.appendChild(styleSheet); var elem = document.getElementById('myElement'); elem.style.animationName = 'dynamicSlideIn'; elem.style.animationDuration = duration; elem.style.animationFillMode = 'forwards';