你还在用setTimeOut保证页面刷新完成后执行吗?试试requestAnimationFrame应用场景吧
## 前言 在前端开发中,我们经常需要在页面刷新、动画执行或 DOM 更新完成后执行某些操作。许多开
渲染中...
## 前言
在前端开发中,我们经常需要在页面刷新、动画执行或 DOM 更新完成后执行某些操作。许多开发者习惯使用 `setTimeout` 来延迟执行代码,试图等待浏览器完成渲染。但这种方式不仅不够精准,还可能导致性能问题和用户体验下降。今天,我们就来深入了解一下浏览器专门为动画和渲染优化提供的 API —— **requestAnimationFrame**,以及它在各种场景中的应用。
<!-- more -->
## 为什么不要再依赖setTimeout?
### 1. 延时不精准
使用 `setTimeout` 固定延时,通常我们会设置一个类似 `100ms` 或 `16ms` 的延时,但浏览器的渲染和重绘并不是严格按照这个时间间隔执行的。延时设置过长,用户会感到操作迟缓;延时设置过短,则可能还没等到 DOM 更新完毕,代码就开始执行,导致意外错误。
### 2. 帧率和性能问题
`setTimeout` 无法保证与浏览器的刷新率同步。例如,在动画执行过程中,如果浏览器刷新率为 60Hz,理想情况下每帧更新应该在 16.67ms 左右。使用 `setTimeout` 可能会错过理想的帧率,导致动画跳帧或不流畅,甚至浪费 CPU 资源。
### 3. 后台标签页依然消耗资源
当页面处于后台时,`setTimeout` 仍然会按照设定的时间间隔运行,而浏览器可能会暂停某些动画和渲染操作。此时,代码与用户看不见的页面状态不同步,容易产生不必要的性能浪费。
## requestAnimationFrame —— 动画和DOM更新的最佳拍档
**requestAnimationFrame** 是浏览器为实现流畅动画和高效 DOM 更新而设计的 API。它会在浏览器下一次重绘前执行指定的回调函数,确保代码执行时正好赶上页面渲染的最佳时机。
### 工作原理
- **与浏览器刷新同步**
当你调用 `requestAnimationFrame(callback)` 时,浏览器会在下次重绘前调用 `callback`。通常,显示器的刷新率是 60Hz,也就是每秒 60 帧,这样每帧大约 16.67ms。
- **自动优化**
如果页面处于后台,浏览器会自动暂停 `requestAnimationFrame` 的回调,这样可以降低 CPU 使用率,节省电池能耗。
- **高精度时间戳**
回调函数会自动传入一个高精度的时间戳,开发者可以利用它计算动画进度,实现精准的动画效果。
### 常见应用场景
#### 1. 平滑动画与交互效果
对于元素移动、缩放、渐变等动画效果,使用 `requestAnimationFrame` 可以确保每一帧都与浏览器的重绘周期同步,动画更流畅、更自然。
例如,下面的代码展示了如何用 `requestAnimationFrame` 实现一个简单的平移动画:
```javascript
function animate(timestamp) {
// 根据传入的时间戳计算动画进度
const progress = timestamp - startTime;
element.style.transform = `translateX(${Math.min(progress / 10, 200)}px)`;
// 当动画还未结束时继续下一帧动画
if (progress < 2000) {
requestAnimationFrame(animate);
}
}
const startTime = performance.now();
requestAnimationFrame(animate);
```
#### 2. 页面滚动和视差效果
在需要根据用户滚动实时更新页面内容或实现视差效果时,使用 `requestAnimationFrame` 能够保证滚动事件与渲染同步,从而提升页面流畅性。例如:
```javascript
let ticking = false;
window.addEventListener('scroll', () => {
if (!ticking) {
requestAnimationFrame(() => {
updateParallaxEffect(); // 根据滚动位置更新页面元素
ticking = false;
});
ticking = true;
}
});
```
#### 3. Canvas 动画和游戏开发
在使用 Canvas 绘制动画或开发小游戏时,每一帧的更新都至关重要。`requestAnimationFrame` 不仅可以确保动画的流畅性,还能根据浏览器实际刷新频率自动调整动画步伐。例如:
```javascript
function gameLoop(timestamp) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
updateGameState(timestamp);
renderGame(ctx);
requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);
```
#### 4. 数据可视化与实时图表
实时更新图表、股票行情、网络流量监控等数据可视化场景中,使用 `requestAnimationFrame` 可以确保图表更新与页面刷新同步,避免因延时问题导致的数据展示不连贯问题。
## 总结
在现代前端开发中,不再建议使用 `setTimeout` 来等待页面渲染或动画更新完成。相比之下,`requestAnimationFrame` 更加高效、精准,并且能自动与浏览器的渲染周期保持同步。无论你是在制作平滑的动画、处理滚动视差效果,还是在开发 Canvas 游戏和实时数据可视化项目,`requestAnimationFrame` 都能为你带来更好的用户体验和性能表现。
下次当你需要等待 DOM 更新或执行动画时,试试用 `requestAnimationFrame`,让页面刷新更智能、更流畅吧!END
评论
登录后查看和发表评论
前往登录