《TypeScript图形渲染实战:2D架构设计与实现》 —3.1.2 requestAnimationFrame与监视器
3.1.2 requestAnimationFrame与监视器刷新频率
根据图3.1所示,通过requestAnimationFrame方法启动step回调函数后,每次调用step函数的时间间隔固定在16.66毫秒左右,基本上每秒调用60次step函数(1000 / 60 约等于16.66毫秒,其中1秒等于1000毫秒)。
每秒step函数调用的次数(频率)实际上是和监视器屏幕刷新次数(频率)保持一致。笔者在自己的Windows笔记本电脑上做了个实验,看一下监视器的屏幕刷新频率对requestAnimationFrame方法的影响。默认情况下,笔者的Windows系统电脑的监视器屏幕刷新频率是60赫兹,可以人为认定监视器每秒刷新重绘60次,如图3.2所示,将屏幕刷新频率60赫兹更改为48赫兹,来看看结果会怎样。
图3.2 更改监视器屏幕刷新频率
然后运行3.1节所示的代码,会得到如图3.3所示的结果。
图3.3 监视器屏幕刷新频率48赫兹下Chrome浏览器中的运行效果
从图3.3中会看到,每次调用step函数的时间间隔固定在20.83毫秒左右,符合当前监视器屏幕刷新频率48赫兹的设置(1000 / 48 约等于20.83毫秒),由此可见request Animation Frame是一个与硬件相关的方法,该方法会保持与监视器刷新频率一致的状态。
再来看一下3.1节中的step函数,会发现它很简单,只是输出3个时间差,这种操作本身花不了多少时间,因此能保持16毫秒的频率一直稳定运行是很正常的。那么,如果在step中进行大量耗时操作(恢复到监视器屏幕刷新频率60赫兹的情况下),结果会如何呢?
继续做个实验来看看,在step函数的count ++代码后面添加如下代码:
// 每次调用step就做累加操作
let sum : number = 0 ;
// 每次调用step后,随机生成一个区间位于[5百万,6百万]之间的数num
// 然后从0累加到num,这样每次操作都需要耗费一定的时间,并且具有不同的结果
// 目的是不让JS解释器优化,看看每次暴力穷举所耗费的时间
// 其中Math . random ( )函数返回[ 0 , 1 ]之间的浮点数
// 通过 a + Math . random ( ) * b公式可以生成区间位于[ a , b ]之间的随机数
let num : number = 5000000 + Math . random ( ) * 1000000 ;
for ( let i : number = 0 ; i < num ; i++ ) {
sum ++ ;
}
运行上述程序后,会得到如图3.4所示的结果。
图3.4 Chrome浏览器中step函数在500~600万级别累加计时测试
通过图3.4会看到,两次step调用间隔所耗时间有很明显的波动,但是通过统计,会发现一个很明显的规律,具体如表3.1所示。
表3.1 Chrome浏览器中两帧时间间隔和监视器屏幕刷新频率之间的关系统计表
根据表3.1统计数据会发现,两帧之间的时间间隔(intervalMsec)总是16.66毫秒的倍数(当前监视器屏幕刷新频率60赫兹,折算成每帧需要16.66毫秒刷新一次)。
由此可见,requestAnimationFrame方法会稳定间隔时间:
* 如果当前的回调操作(step函数)在16.66毫米内能完成,那么requestAnimationFrame会等到16.66毫秒时继续下一次step回调函数的调用。
* 如果当前的回调操作(step函数)大于16.66毫秒,则会以16.66毫秒为倍数的时间间隔进行下一次step回调函数的调用。
* 当将监视器屏幕刷新频率60赫兹设置成48赫兹时,结果也类似,两帧之间间隔时间总是20.83毫秒的倍数。
- 点赞
- 收藏
- 关注作者
评论(0)