requestAnimationFrame函数的理解心得

这段时间在研究微信的小游戏开发,看到requestAnimationFrame这个函数不明所以,查了不少资料依然一知半解。后来一段演示让我豁然开朗。

先看下AI怎么说:

  • 起源‌:最初由浏览器厂商引入(如 WebKit 的 webkitRequestAnimationFrame),用于优化动画性能。
  • 标准化‌:2013 年纳入 W3C 规范 Timing control for script-based animations,成为无前缀的标准 API。
  • 功能目标‌:替代 setTimeout/setInterval 实现动画,自动匹配屏幕刷新率(通常 60Hz),避免过度渲染。

据说这个 requestAnimationFrame 函数就是用来替代 setTimeoutsetInterval这两个函数的。这两个函数的作用想必很多人都了解,就是设置一个时间间隔,让指定的函数在每个时间间隔执行。比如下面的代码:

function printTime() {
  console.log(new Date().toLocaleTimeString());
}

const intervalId = setInterval(printTime, 1000);

通过setInterval让printTime()函数每间隔一秒就执行一次。或者也可以用setTimeout实现:

function repeat() {
  // 你的任务逻辑
  console.log("执行任务,时间:", new Date().toLocaleTimeString());

  // 递归调用 setTimeout,实现间隔
  setTimeout(repeat, 1000); 
}

// 启动定时任务
repeat();

据说,以前的前端或者网页开发人员,为了实现动画效果,仿效电影的每秒在屏幕上输出24帧的原理,让显示器在一秒内输出若干帧,就达到了动画的效果。那一秒要输出多少帧呢?一般而言是60帧,为什么是60而不是其他数值?因为绝大多数屏幕的刷新率为 ‌60Hz‌(每秒刷新 60 次),每帧间隔约 ‌16.67ms‌。若动画帧率匹配刷新率,可实现最流畅的视觉效果。

后来,网页上的动画开发的需求可能是越来越多,于是requestAnimationFrame应运而生。这个函数不是每个环境都支持。我试过了,在原生的node.js环境下不能支持,想也容易明白,node.js对动画好像没什么需求。所以我们直接在浏览器环境中运行:打开edge或者其他浏览器->按下f12->在控制台复制如下代码:

let animationID;
function startAnimation() {
  animationID = requestAnimationFrame(animate);
}

function animate() {
  console.log("动画执行中"+(new Date()).toLocaleString());
  animationID = requestAnimationFrame(animate); // 循环调用
}

function stopAnimation() {
  cancelAnimationFrame(animationID); // 通过ID停止
}
startAnimation();

当敲回车让代码执行后,我们看到以下的输出:

注意看最前面的数字,有的是52,更多的是60,最后那个29是还在执行累计中,最后也应该差不多是累计到60。

而笔者的显示器是60hz,也就是说每秒钟屏幕会整个刷新60次。而requestAnimationFrame与上面两个函数的最大差别是,它不需要手动指定时间间隔,自动匹配显示器的刷新率。假如用setInterval实现类似的输出,则代码大概如下:

var i = 0;
// 示例:每隔1000/60秒打印当前时间
function printTime() {
  console.log(`${++i} :`+new Date().toLocaleTimeString());
}

// 启动定时器(间隔1000毫秒)
const intervalId = setInterval(printTime, 1000/60);

// 5秒后停止定时器
setTimeout(() => {
  clearInterval(intervalId);
  console.log("定时器已停止");
}, 5000);

1000/60是个硬编码,假如在一台刷新率120hz的显示器上,这个地方估计得改。但requestAnimationFrame会自动匹配。下面我更改下我显示器的刷新率,改成50hz。再次运行浏览器的代码,结果如下:

看到最前面的重要次数变成了50次,也就是说requestAnimationFrame根据当前显示器每秒刷新50次的频率,同步更新输出。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值