requestAnimationFrame(rAF)使用,与传统方法(如 setTimeout/setInterval),直观展示 rAF 的优势
目录
- 核心优势
- 适用场景
- 案例对比(含代码)
- 案例一:基础动画(方块移动)
- 案例 2:高频更新(Canvas 粒子动画)
- 总结
核心优势
- 与浏览器渲染流程深度同步,避免无效计算
- 自动暂停后台任务,节省资源
- 减少布局抖动和重复渲染,提升复杂动画性能
适用场景
适用场景:所有需要高频更新视觉状态的动画、游戏、数据可视化等
案例对比(含代码)
案例一:基础动画(方块移动)
性能对比
指标 | setInterval | rAF |
---|---|---|
流畅度 | 出现卡顿(丢帧) | 平滑稳定 |
实际效果 | 方块移动不连贯 | 方块匀速平滑移动 |
实际cpu占比情况和重绘的性能无明显差别
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>rAF方块移动案例</title>
<style>
#box {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
<script>
// const box = document.getElementById("box");
// let position = 0;
// function moveBox() {
// position += 2;
// box.style.left = position + "px";
// if (position >= 1000) {
// clearInterval(intervalId);
// }
// }
// const intervalId = setInterval(moveBox, 16); // 模拟 60FPS
const box = document.getElementById("box");
let position = 0;
function moveBox() {
position += 2;
box.style.left = position + "px";
if (position < 1000) {
requestAnimationFrame(moveBox);
}
}
requestAnimationFrame(moveBox);
</script>
</html>
案例 2:高频更新(Canvas 粒子动画)
性能对比
指标 | setInterval | rAF |
---|---|---|
帧率(FPS) | 帧率不稳定47-60 FPS | 稳定接近 60 FPS |
GPU 占用 | 高 | 优化后的绘制调用,GPU 压力更低 |
该案例下未感觉出明显的卡顿,内存相差不大,cpu较为明显
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用 requestAnimationFrame 的粒子动画</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const particles = Array.from({ length: 1000 }, () => ({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: Math.random() * 2 - 1,
vy: Math.random() * 2 - 1,
}));
// 使用setTimeout实现动画
function updateParticles() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
particles.forEach((p) => {
p.x += p.vx;
p.y += p.vy;
// 边界反弹
if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
if (p.y < 0 || p.y > canvas.height) p.vy *= -1;
ctx.fillRect(p.x, p.y, 2, 2);
});
setTimeout(updateParticles, 16);
}
updateParticles();
// 使用requestAnimationFrame实现动画
// function updateParticles() {
// ctx.clearRect(0, 0, canvas.width, canvas.height);
// particles.forEach((p) => {
// p.x += p.vx;
// p.y += p.vy;
// if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
// if (p.y < 0 || p.y > canvas.height) p.vy *= -1;
// ctx.fillRect(p.x, p.y, 2, 2);
// });
// requestAnimationFrame(updateParticles);
// }
// requestAnimationFrame(updateParticles);
</script>
</body>
</html>
总结
requestAnimationFrame 的核心优势是与浏览器渲染流程深度集成,通过减少无效渲染、自动节流、帧率同步等机制,显著提升动画性能