requestAnimationFrame
方法
requestAnimationFrame
是一个 JavaScript 中用于优化动画的高效方法。它告诉浏览器希望执行一个动画,并在下一次重绘之前调用指定的回调函数来更新动画。这种方式能够更好地协调动画更新和屏幕刷新率,从而提高性能和流畅度。
语法
let requestId = requestAnimationFrame(callback);
参数
- callback: 要执行的回调函数。
该回调函数会在浏览器即将重绘前调用,接收一个参数:- timestamp: DOM 高精度时间戳(以毫秒为单位),表示回调被触发的时间。
返回值
- 返回一个整数值
requestId
,可以通过它取消后续的回调调用。
特点
- 自动优化:
requestAnimationFrame
会根据设备刷新率(通常是 60 次每秒)来决定回调函数的调用频率。 - 省资源:在标签页不可见(如切换到后台)时,动画会自动暂停,节省 CPU 和电池。
- 流畅的动画:相比
setTimeout
和setInterval
,requestAnimationFrame
提供更平滑的动画。
示例代码
创建一个动画
let start = null;
function step(timestamp) {
if (!start) start = timestamp;
const progress = timestamp - start;
// 将动画移动到距离左边的 `progress` 像素处
element.style.transform = `translateX(${Math.min(progress, 200)}px)`;
// 如果尚未完成动画,则继续调用
if (progress < 200) {
requestAnimationFrame(step);
}
}
// 开始动画
requestAnimationFrame(step);
停止动画
let requestId;
function startAnimation() {
requestId = requestAnimationFrame(step);
}
function stopAnimation() {
cancelAnimationFrame(requestId);
}
取消回调
如果需要停止动画,可以使用 cancelAnimationFrame
方法:
cancelAnimationFrame(requestId);
<style lang='scss' scoped>
.container {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.count { margin-right: 20px; }
</style>
<template>
<div class="container">
<span class="count"> {{ count }} </span>
<cx-button @click="test">开始</cx-button>
<cx-button @click="stopAnimation">结束</cx-button>
</div>
</template>
<script>
export default
{
data()
{
return {
count: 10000
}
},
methods:
{
test()
{
this.count--
if (this.count > 1)
this.requestId = requestAnimationFrame(this.test)
},
stopAnimation()
{
cancelAnimationFrame(this.requestId)
}
}
}
</script>
兼容性
requestAnimationFrame
已被现代浏览器广泛支持,但在早期版本中需要使用前缀:
- Webkit:
webkitRequestAnimationFrame
- Mozilla:
mozRequestAnimationFrame
常见应用场景
- 页面动画:如移动元素、改变颜色。
- 游戏开发:流畅的游戏画面更新。
- 滚动效果:根据用户滚动动态调整页面内容。
总之,requestAnimationFrame
是开发高性能动画的首选方法!