-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
【Canvas杂谈:第一季】RAF/FPS/dt干嘛用? #1
Comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
写在前面的话
我们今天要说的故事。要从RAF开始。
首先,RAF是什么?我相信大部分正在阅读此文的同学应该正在使用chrome浏览器。打开控制台,敲出
webkitRequestAnimationFrame
.小编不会赘述这个东西干嘛用的,知道的同学已经知道了,不太了解的同学随便google一下也就知道了。说的简单一点,它就是个计时器 干着和
setTimeout(callback, 16)
类似的事情。为什么偏偏是
setTimeout(callback, 16)
?不知道大家对上面的16ms有什么疑义没?
两三年前当js动画的计时器都是使用
setTimeout
和setInterval
来实现的时候。小编曾经有过以下的蠢事。所以曾经做过一件事:
最后发现其实
setInterval
这种东西是有个最小的时间间隔的。比如小编现在在用的chrome里面 setInterval 的最小时间间隔就是4ms。但是就算给他设置4ms的interval 它也不是4ms,因为... 我们还要考虑setInterval中的function的运行时间... 说到这里,剩下的小伙伴们自己去想吧。
好吧,回到开始的 16ms的话题。为什么16ms是合适的,而不是10ms或者20ms。当然这跟我们的人体工程有关系。有医学研究发现我们人眼对于刷新率的感知。每秒60帧几乎就满足了我们的眼睛。意思就是好像你花个5k块钱买个刷新率每秒200帧的电视看起来跟别人1k块的刷新率每秒60帧的电视看起来流畅度差不多... 汗!!
那么16ms 和60帧又有什么关系呢? 请打开计算器 计算一下, 1秒 = 1000毫秒, 1000/60 = ??
就算群众的眼睛是雪亮的..60帧也足够了。
16ms和RAF又有什么关系呢??
请看图,不解释 💯
然后,我们要说的是RAF和setInterval(callback, 16)以及setTimeout(callback, 16) 的关系
在扯之前,先让大家看两个demo 【图片可点】。
这两个实现的是同一个东西,虽然不是canvas实现的东西,但是跟RAF和setInterval有关。我相信大家用浏览器打开这两个demo看到的效果是一样的。当然,浏览器需要支持RAF,然后,请按下面的操作做:
setInterval 和 setTimeout 在非当前窗口,或者浏览器‘休眠’的时候,即使渲染停止了,但是计时器不会休息,仍然会顽强的跑着!
这其实是一个不好的讯息。会大大加重浏览器的负担,同时也会影响这个页面或者app本身的性能。
以上,为第一个明显的不同的地方。
第二个不同的地方,在于callback队列的不同。小编举个栗子:
C来安排任务的机制会比B稍微好一点点,但终究也逃不了B的厄运,身上的负担会越来越重。
我们来看A做这件事情的过程。
所以,A完成10次任务所花的时间应该是1000ms,但是B和C完成10次任务应该需要>=1000ms,因为他们还要分心去管理他们的任务队列。
做个更形象的比喻:
结果是你都花10天做完了10个任务,请问你觉得你更喜欢哪种方式??
RAF说完了,我们来说说FPS和dt
我们都知道要让canvas里面的东西动起来,本质上你在位置1画了一个矩形,然后擦掉,然后在位置二画了一个同样的矩形。所以,这个矩形从位置一运动到了位置二。
我们把这个过程叫做“一帧”。
FPS: Frame Per Second, 翻译过来是每秒的帧数。
dt: Delta Time, 翻译过来是时间差,或者每帧的时间间隔。
理论上,fps和dt的关系就是 FPS = 1s/dt 。他们都是用来表示一个系统每秒能够运行的帧数的。简单来说,这两个东西可以反应动画的流畅程度。
那么,FPS通常是怎么获取到的呢?
我们看一个demo:
这是小编闲暇时用粒子的双密度松弛算法做的简单的流体模拟实验。我们来说说右上角的fps是怎么得到的呢?
根据 FPS= 1/dt. 所以首先我们先去拿到这个帧的时间间隔dt。在你的动画循环计数器开始的时候记录下来时间,和上一次记录下来的时间相减,就能简单得到一个当前帧的时间差dt。
代码就不多说,我想大家应该都知道怎么做。拿到dt之后,换算成fps,按合适的时间抛出来就可以了。
如果你觉得麻烦,推荐大家使用 mrdoob/stats.js
最后一个问题:dt 除了可以反应动画流畅度之外,还有什么用??
小编猜测,应该好多的同学没有意识到dt这个时间差在动画,或者游戏里面还有一个莫大的用处。
举一个场景:
这。。。显然不是我们期望的。
接下来,每帧的时间差dt就派上用场了。如果我们在每帧的update里面这样写:
好的机器上,用户按下方向键1s,游戏执行60帧,每帧的间隔dt是1/60, dt_60 就是1,每帧人物移动1的距离。1s移动60的距离。
坏的机器上,游戏执行30帧,dt=1/30, dt_60=2; 也就是每帧人物会移动2的距离,那么1s下来,人物移动总距离还是60.
说到这里,小编觉得应该忽然明白了什么。。。
本期的【Canvas杂谈】到此为止,总结一下:
【完】
The text was updated successfully, but these errors were encountered: