目錄
一、核心概念與語法
1.?@keyframes?關鍵幀
2.?animation?屬性
二、動畫調速函數(animation-timing-function)
1.?預設值
2.?貝塞爾曲線
3.?步進函數(steps())
三、動畫控制與交互
1.?暫停與恢復
2.?JavaScript 控制
3.逐幀動畫與精靈圖
四、性能優化
五、實際應用示例
1.?淡入淡出效果
2.?旋轉加載圖標
3.?彈跳效果
六、兼容性與前綴
示例:走馬燈
示例:全民出游季
CSS 動畫允許通過定義關鍵幀(
@keyframes
)和動畫屬性(animation
)實現復雜的動態效果,相比?transition
?更靈活,支持多階段控制和循環播放。
一、核心概念與語法
在 CSS 中,以?@
?開頭的語法稱為?At-Rules(規則聲明),用于定義 CSS 的元數據、條件邏輯、外部資源引入等高級功能。
1.?@keyframes
?關鍵幀
-
作用:定義動畫的中間狀態。
-
語法:
@keyframes 動畫名稱 {from { /* 初始狀態 */ }to { /* 結束狀態 */ }/* 或使用百分比 */0% { ... }50% { ... }100% { ... } }
-
示例:
@keyframes fadeIn {from { opacity: 0; }to { opacity: 1; } }@keyframes slideAndRotate {0% { transform: translateX(0) rotate(0); }50% { transform: translateX(200px) rotate(180deg); }100% { transform: translateX(0) rotate(360deg); } }
2.?animation
?屬性
?
-
作用:將關鍵幀動畫應用到元素。
-
子屬性:
屬性 作用 常用值 animation-name
指定關鍵幀名稱 fadeIn
,?slideAndRotate
animation-duration
動畫持續時間 2s
,?500ms
animation-timing-function
速度曲線 ease
(默認),?linear
,?ease-in-out
,?cubic-bezier(0.4, 0, 0.2, 1)
animation-delay
動畫延遲時間 1s
,?0.5s
animation-iteration-count
播放次數 1
(默認),?infinite
,?3
animation-direction
播放方向 normal
(默認正向),?reverse
(反向),?alternate
(正反交替)animation-fill-mode
動畫結束后的樣式保留 none
(默認),?forwards
(保持最后一幀),?backwards
(應用第一幀)animation-play-state
控制播放狀態 running
(默認),?paused
(暫停) -
簡寫語法:
.element {animation: name duration timing-function delay iteration-count direction fill-mode play-state; }
示例:
.box {animation: fadeIn 2s ease-in-out 1s infinite alternate forwards; }
二、動畫調速函數(animation-timing-function
)
1.?預設值
-
ease
:默認緩入緩出(先加速后減速)。 -
linear
:勻速。 -
ease-in
:緩入(逐漸加速)。 -
ease-out
:緩出(逐漸減速)。 -
ease-in-out
:緩入緩出。
2.?貝塞爾曲線
-
使用?
cubic-bezier(x1, y1, x2, y2)
?自定義速度曲線。
.box {animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
}
3.?步進函數(steps()
)
-
將動畫拆分為固定步數播放,適合幀動畫。
.box {animation-timing-function: steps(5, jump-start); /* 分 5 步跳躍播放 */ }
三、動畫控制與交互
1.?暫停與恢復
-
通過?
animation-play-state
?控制:.box:hover {animation-play-state: paused; /* 懸停時暫停動畫 */ }
2.?JavaScript 控制
-
動態添加/移除動畫類:
const box = document.querySelector('.box'); box.classList.add('fadeIn'); // 觸發動畫 box.style.animation = 'none'; // 停止動畫
3.逐幀動畫與精靈圖
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>test</title><link rel="stylesheet" href="./iconfont/iconfont.css"><style>.box {margin: 100px auto;width: 1000px;}.people {width: 140px;height: 140px;background-image: url(./res/run.png);animation: run 1s steps(12) infinite,move 4s linear infinite;}@keyframes run {from {background-position: 0 0;}to {background-position: -1680px 0;}}@keyframes move {0% {transform: translate(0) scaleX(1);}50% {transform: translate(800px) scaleX(1);}50.1% {transform: translate(800px) scaleX(-1);}100% {transform: translate(0) scaleX(-1);}}</style>
</head>
<body><div class="box"><div class="people"></div></div></body>
</html>
?
四、性能優化
-
優先使用?
transform
?和?opacity
-
這些屬性由 GPU 加速,避免觸發重排(如?
width
、margin
)。
-
-
減少動畫數量
-
同時運行過多動畫可能導致頁面卡頓。
-
-
使用?
will-change
?提示瀏覽器.box {will-change: transform, opacity; /* 提前告知瀏覽器可能變化的屬性 */ }
五、實際應用示例
1.?淡入淡出效果
@keyframes fadeInOut {0%, 100% { opacity: 0; }50% { opacity: 1; }
}.element {animation: fadeInOut 3s ease-in-out infinite;
}
2.?旋轉加載圖標
@keyframes spin {from { transform: rotate(0deg); }to { transform: rotate(360deg); }
}.loader {animation: spin 1s linear infinite;
}
3.?彈跳效果
@keyframes bounce {0%, 100% { transform: translateY(0); }50% { transform: translateY(-30px); }
}.button {animation: bounce 1s ease-in-out infinite;
}
六、兼容性與前綴
-
現代瀏覽器:無需前綴(Chrome 43+、Firefox 16+、Safari 9+)。
-
舊版瀏覽器:需添加?
-webkit-
?前綴:@-webkit-keyframes fadeIn { ... } .box {-webkit-animation: fadeIn 2s; }
示例:走馬燈
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>test</title><link rel="stylesheet" href="./iconfont/iconfont.css"><style>* {margin: 0;padding: 0;box-sizing: border-box;}li {list-style: none;}a {text-decoration: none;color: #fff;}.box {margin: 100px auto;width: 300px;height: 50px;overflow: hidden;}.box ul {display: flex;animation: move 7s linear infinite;}.box:hover ul {animation-play-state: paused;}@keyframes move {from {transform: translateX(0);}to {transform: translateX(-700px);}}.box img {width: 100px;}</style>
</head>
<body><div class="box"><ul><li><img src="./res/1.jpg" alt=""></li><li><img src="./res/2.jpg" alt=""></li><li><img src="./res/3.jpg" alt=""></li><li><img src="./res/4.jpg" alt=""></li><li><img src="./res/5.jpg" alt=""></li><li><img src="./res/6.jpg" alt=""></li><li><img src="./res/7.jpg" alt=""></li><!-- 填補顯示區域的空白 --><li><img src="./res/1.jpg" alt=""></li><li><img src="./res/2.jpg" alt=""></li><li><img src="./res/3.jpg" alt=""></li></ul></div></body>
</html>
示例:全民出游季
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>test</title><link rel="stylesheet" href="./iconfont/iconfont.css"><style>* {margin: 0;padding: 0;box-sizing: border-box;}li {list-style: none;}a {text-decoration: none;color: #fff;}html {height: 100%; }body {height: 100%;background: url(./res/images/f1_1.jpg) no-repeat center 0 / cover; }.cover {width: 100%;height: 100%; position: relative;}.cover div {position: absolute;}.title {top: 50%;left: 50%;transform: translate(-50%,-50%);animation: show 1s;}@keyframes show {0% {transform: translate(-50%,-50%) scale(1);}20% {transform: translate(-50%,-50%) scale(0.3);}50% {transform: translate(-50%,-50%) scale(1.7);}80% {transform: translate(-50%,-50%) scale(0.8);}100% {transform: translate(-50%,-50%) scale(1);}}.label {bottom: 10%;left: 50%;transform: translate(-50%);}.label ul {display: flex;justify-content: space-between;}.label ul img {width: 100px;margin: 0 85px;animation: bounce .8s ease-in infinite alternate;}.label ul li:nth-child(2) img {animation: bounce .8s 0.3s ease-in infinite alternate;}.label ul li:nth-child(3) img {animation: bounce .8s 0.6s ease-in infinite alternate;}.label ul li:nth-child(4) img {animation: bounce .8s 0.9s ease-in infinite alternate;}@keyframes bounce {from {transform: translateY(0);}to {transform: translateY(30px);}}.cloud {position: relative;left: 50%;}.cloud img:nth-child(1) {top: 20px;margin-left: -200px;}.cloud img:nth-child(2) {top: 100px;margin-left: 400px;}.cloud img:nth-child(3) {top: 180px;margin-left: -500px;}.cloud img {position: absolute;animation: move 2s linear infinite alternate;}@keyframes move {to {transform: translate(-50px);}}.lu {top: 15%;left: 60%;}.san {top: 15%;left: 25%;animation: float 1.5s linear infinite alternate;}@keyframes float {to {transform: translateY(50px);}}</style>
</head>
<body><div class="cover"><div class="cloud"><img src="./res/images/yun1.png" alt=""><img src="./res/images/yun2.png" alt=""><img src="./res/images/yun3.png" alt=""></div> <div class="lu"><img src="./res/images/lu.png" alt=""></div> <div class="san"><img src="./res/images/san.png" alt=""></div><div class="label"><ul><li><img src="./res/images/1.png" alt=""></li><li><img src="./res/images/2.png" alt=""></li><li><img src="./res/images/3.png" alt=""></li><li><img src="./res/images/4.png" alt=""></li></ul></div><div class="title"><img src="./res/images/font1.png" alt=""></div></div></body>
</html>