前端动画实现方式
CSS、JavaScript、Canvas、SVG 等多种前端动画实现方案对比
问题
前端实现动画有哪些方式?各有什么特点?
解答
1. CSS Transition
用于设置样式属性从一种状态平滑过渡到另一种状态。
div {
width: 50px;
height: 50px;
background-color: pink;
transition: width 1s ease 0s;
}
div:hover {
width: 200px;
}
语法:transition: property duration timing-function delay;
默认值:transition: all 0 ease 0;
2. CSS Animation
通过 @keyframes 定义关键帧,实现逐帧动画,可以精确控制动画过程中的各个阶段。
div {
width: 50px;
height: 50px;
background-color: pink;
animation: move 2s ease infinite;
}
@keyframes move {
0% {
transform: translateX(0);
}
50% {
transform: translateX(200px);
}
100% {
transform: translateX(0);
}
}
与 jujns 的区别:transition 只需指定开始和结束状态,animation 可以设置多个关键帧。
3. JavaScript 动画
通过 setInterval 或 setTimeout 持续改变元素样式。
const div = document.querySelector('div');
let left = 0;
setInterval(() => {
left += 1;
div.style.left = left + 'px';
}, 16); // 约 60fps
一般认为人眼能辨识的流畅动画为每秒 60 帧,即每帧约 16ms。移动端使用 JS 动画可能会有卡顿,需要注意性能优化。
4. Canvas 动画
通过 Canvas API 绘制动画,适合复杂动画场景。
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let x = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'pink';
ctx.fillRect(x, 50, 50, 50);
x += 2;
if (x > canvas.width) x = 0;
requestAnimationFrame(draw);
}
draw();
优势是可以应对页面中多个动画元素渲染较慢的情况,完全通过 JavaScript 控制动画执行。
5. SVG 动画
SVG 是基于 XML 的矢量图形,可以使用 CSS 和 JavaScript 控制动画。
<svg width="200" height="200">
<circle cx="50" cy="50" r="20" fill="pink">
<animate attributeName="cx" from="50" to="150" dur="2s" repeatCount="indefinite" />
</circle>
</svg>
优势:矢量图不失真、体积小、可用 CSS/JS 交互、利于 SEO。
6. jQuery animate()
通过 jQuery 的 animate() 方法创建动画,只支持数字值属性。
$(document).ready(function() {
$('#btn1').click(function() {
$('#box').animate({ height: '300px' });
});
$('#btn2').click(function() {
$('#box').animate({ height: '100px' });
});
});
7. GIF 图片
直接使用 GIF 动图,实现简单但不够灵活。
<img src="animation.gif" alt="动画">
关键点
- CSS 动画简单场景代码更简洁,复杂动画用 JS 更灵活,可以控制暂停、取消等
- CSS 动画性能更好(GPU 加速),JS 动画需要经过 JS 引擎解析后再渲染
- CSS 动画存在浏览器兼容问题,JS 动画兼容性更好
- Canvas 适合多元素复杂动画,SVG 适合矢量图形动画且利于 SEO
- 移动端优先使用 CSS 动画,桌面端可以使用 JS 动画实现更复杂的交互
目录