CSS 逐幀動畫實現指南
逐幀動畫(frame-by-frame animation)是一種通過快速連續顯示一系列靜態圖像來創造運動效果的技術。以下是使用CSS實現逐幀動畫的幾種方法。
1. 使用 steps()
計時函數
這是實現逐幀動畫最常用的方法,通過animation-timing-function
的steps()
函數實現。
.sprite {width: 100px;height: 100px;background-image: url('sprite-sheet.png');animation: play 1s steps(6) infinite;
}@keyframes play {from { background-position: 0 0; }to { background-position: -600px 0; }
}
參數說明:
steps(6)
- 表示動畫分為6步完成-600px
- 雪碧圖總寬度(6幀 × 每幀100px)
2. 完整雪碧圖動畫示例
<!DOCTYPE html>
<html>
<head>
<style>.character {width: 64px;height: 64px;background-image: url('https://example.com/walk-cycle.png');background-position: 0 0;animation: walk 1s steps(8) infinite;}@keyframes walk {from { background-position: 0 0; }to { background-position: -512px 0; } /* 8幀 × 64px */}
</style>
</head>
<body><div class="character"></div>
</body>
</html>
3. 多行雪碧圖處理
對于包含多行動畫的雪碧圖:
.sprite {width: 64px;height: 64px;background-image: url('multi-row-sprite.png');animation: play 0.8s steps(8) infinite;
}/* 行走動畫 */
.walk {animation-name: walk;
}@keyframes walk {from { background-position: 0 0; }to { background-position: -512px 0; }
}/* 跳躍動畫 */
.jump {animation-name: jump;
}@keyframes jump {from { background-position: 0 -64px; } /* 第二行 */to { background-position: -512px -64px; }
}
4. 使用多個DOM元素實現逐幀動畫
如果不使用雪碧圖,可以通過切換多個元素的顯示來實現:
<div class="frame-animation"><img src="frame1.png" class="frame active"><img src="frame2.png" class="frame"><img src="frame3.png" class="frame"><img src="frame4.png" class="frame">
</div>
.frame-animation {position: relative;width: 100px;height: 100px;
}.frame {position: absolute;top: 0;left: 0;opacity: 0;animation: frameAnimation 1s infinite;
}.frame.active {opacity: 1;
}@keyframes frameAnimation {0%, 25% { opacity: 0; }25.1%, 50% { opacity: 1;z-index: 1;}50.1%, 75% { opacity: 0;z-index: 0;}75.1%, 100% { opacity: 1;z-index: 1;}
}.frame:nth-child(1) { animation-delay: 0s; }
.frame:nth-child(2) { animation-delay: 0.25s; }
.frame:nth-child(3) { animation-delay: 0.5s; }
.frame:nth-child(4) { animation-delay: 0.75s; }
5. 使用CSS自定義屬性控制動畫幀
:root {--frame-count: 8;--frame-width: 64px;
}.sprite {width: var(--frame-width);height: 64px;background-image: url('sprite.png');animation: play 1s steps(var(--frame-count)) infinite;
}@keyframes play {to {background-position: calc(-1 * var(--frame-count) * var(--frame-width)) 0;}
}
性能優化建議
-
使用will-change:
.sprite {will-change: background-position; }
-
減少復合操作:
- 優先使用
opacity
和transform
屬性 - 避免在動畫中改變
width
/height
等屬性
- 優先使用
-
合理使用硬件加速:
.sprite {transform: translateZ(0); }
-
控制動畫頻率:
@media (prefers-reduced-motion: reduce) {.sprite {animation: none;} }
瀏覽器兼容性
- 現代瀏覽器都支持
steps()
函數 - IE10及以上支持,但可能需要前綴
- 對于更老的瀏覽器,可以使用JavaScript實現回退
高級技巧:與JavaScript結合
// 動態改變動畫速度
const sprite = document.querySelector('.sprite');
sprite.style.animationDuration = '0.5s';// 暫停/播放動畫
function toggleAnimation() {const animation = sprite.style.animationPlayState;sprite.style.animationPlayState = animation === 'paused' ? 'running' : 'paused';
}// 切換不同動畫
function changeAnimation(type) {sprite.style.animationName = type;
}
逐幀動畫是游戲開發和UI動效中常用的技術,合理使用可以創建出流暢的視覺效果,同時保持較好的性能表現。