十三香:聊一聊苹果的动态刷新率

2,369 阅读4分钟

前言

不久前,苹果发布了最新款iPhone13,其中的Pro型号更是史无前例地用上了120Hz ProMotion刷新率的屏幕,并且宣称其刷新率可以在10赫兹到120赫兹之间动态变化以适配具体的场景需求。

于是我想到了之前做canvas开发抽象出来的动画类的代码,似曾相识的感觉。

高刷屏

众所周知,屏幕具备一个刷新率,通常其值为60Hz,也就是说1秒渲染60次,而通常我们所看的视频的帧率一般为30Hz,而电影制式一般为24Hz

通常,刷新率越高,人眼在每秒所观测到的画面越多,那么从视觉观感来说就会越流畅,人所进行的操作通过屏幕反映出来也就更迅速,所以,职业电竞选手,特别是FPS选手,他们给自己挑选的显示器几乎都是144Hz的刷新率往上走,更有甚者刷新率达到了240Hz

苹果的革新

所以,当手指触摸在屏幕上产生了事件或触发了动画时,屏幕立即以最高120帧率运行,这样子保证了用户最佳的体验;而当用户在阅读静止不动的页面时,屏幕恢复到10帧率进行刷新,这样既保证了极佳的用户体验,又大大减少了由于无效重绘而引起的耗电量。

再打个额外的比方,假设正常情况下,我们看一段每秒30帧的视频耗了10%的电,实际上在60Hz的屏幕上,每2帧所渲染出来的视频内容都是一模一样的,此时,动态刷新率登场,将帧率动态地调整为30Hz,那么大致可以说,耗电量可以接近于5%,接近于之前的一半,而实际体验和之前一模一样,可谓是完完全全的物尽其用。

requestAnimationFrame

我不知道苹果系统在底层对于动态刷新率是如何处理的,但我可以说,至少我在HTML5的上层应用层是完完全全可以做到动态刷新的。

HTML5中,有这么一个方法requestAnimationFrame,它在浏览器中属于window对象,处于全局作用域中。

通常,调用此方法,传入需要执行的方法的句柄:

function doSomething(timestamp) {
  console.log(timestamp);
}

requestAnimationFrame(doSomething);

它申请了一个回调,在页面下一帧刷新时,执行doSomething方法,其中的timestamp参数是执行方法时的时间戳。

输出如图:

i1.png

而如果我们要用此方法写一个动画,只需要在doSomething方法中再次调用requestAnimationFrame即可,如下所示:

function doSomething(timestamp) {
  console.log(timestamp);
  requestAnimationFrame(doSomething);
}

输出如图:

i2.png

requestAnimationFrame使得浏览器在每一帧刷新时进行方法的回调,所以它在正常情况下即是以显示器最高帧率进行回调的。

实现

有的没的撤了一堆,接着写点有意思的,也就是说实现类似苹果的动态刷新率。

既然requestAnimationFrame是以最高帧率运行的,那么如果我们设置一个是否执行的前提判断,岂不是就限制了帧率吗?

也就是说,假如我们想要将刷新率动态限制到fps值,那么每次执行间隔应该是1000 / fps,只有当前时间减去上一次执行的时间大于这个时间间隔时,才执行自己的逻辑,那么不就实现了动态刷新率了吗?

var fps = 2; // 在此,我将 fps 限制在 2 帧每秒
var last = 0; // 上次的时间戳

function doSomething(timestamp) {
  if (timestamp - last >= 1000 / fps) { // 当大于时间间隔时执行逻辑
    console.log(timestamp); // 此处执行具体逻辑
    last = timestamp; // 将时间戳记录给 last
  }
  requestAnimationFrame(doSomething);
}

requestAnimationFrame(doSomething);

输出如图:

i3.png

示例

我用canvas写了一个示例,有兴趣的可以自己手动尝试:CodePen 在线演示

  1. 鼠标处于界面外时,刷新率被我主动限制在10Hz
  2. 鼠标移入界面内时,刷新率动态改变至30Hz
  3. 而当鼠标被按下时,刷新率动态改变至最高帧率。

可以很明显的看到,画面中小球执行动画的流畅度。

CodePen 在线演示

GIF.gif

结论

HTML5 canvas动画开发中,实现动态刷新率并不是一件很难的事情,由此我也想到,既然顶层应用层能做到的事,iOS 底层从理论上来说动态刷新率这个技术不应该只是iPhone13 Pro系列所能享有的,因为它和屏幕的素质实在无关,而是在软件层面限制何时应该进行事件回调。

所以,完全有理由期待一下,苹果在未来将此项技术应用给全部产品线也未可知呢?

欢迎批评指正!