帧率(FPS)用于描述成像装置产生连续图像的频率 动画其实就是显示连续帧产生的错觉。如果FPS太低,动画将不平滑,甚至人眼都能看到每一帧图像。 一般运动图像的帧率为24 FPS,电视使用30 FPS。在现代游戏中,玩家必须在视觉跟踪动画对象 ,并迅速作出反应,帧速率一般是每秒30帧和60帧之间。然而,快速移动的物体,可能需要更高的帧速率 ,以避免不希望的视觉假象(闪现)。虽然从理论上讲,我们可以达到极高的帧速率,在FPS由显示器的刷新速率的限制 。现代的液晶电视能120 FPS,甚至240 FPS。在手机,显示器是最有可能限制为60 FPS。
图1:1秒内不同动画帧速率比较
HTML5提供的Web开发人员提供了新的工具来创建动态和交互式内容,如动画和游戏。 帧速率仍作为开发人员的重要指标,fps太低会带来差劲的用户体验。所以开发人员希望有可靠的方式来计算HTML5页面的FPS。 但是问题是,没有办法得到可靠的FPS。 Web开发人员通常通过每次loop和上次loop的间隔来时间time,再通过1000/time来算fps。 微软发布了许多HTML5性能基准测试.如FishIE演示,该演示主要是能够计算Canvas中图像的fps。 。Facebook的JSGamebench主要是计算使用WebGL中展示大量动画的fps。 但是他们没有办法知道浏览器整个网页(整个网页可能包含dom、canvas、webgl、svg..)的FPS。 那么通过JavaScript能否计算出整个网页的fps?
JavaScript的动画
制作动画效果,可以使用的setInterval / setTimeout和requestAnimationFrame。 后者用于制作动画的首选方法。它将告知浏览器你马上要开始动画效果了,浏览器会在下次repaint前调用特定的方法来更新动画以达到优化的结果。
了解定时器在JavaScript中是如何工作是很重要的。 定时器延迟是没法保证的,不准确的,因为所有的JavaScript在单个线程中执行,只有当前面队列执行完毕且轮到了自己才能被执行。 如下图:
如上图所以,不仅时间不够精确,而且由于排队,导致setInterval的一次回调被延迟到了下一轮回调,为了避免同一时间执行多次setInterval的回调, 上次次的将被浏览器放弃执行。
FishIE
所以从上面可以知道,使用setInterval(function(){},16.7)是有可能达不到60fps,是什么导致了回调的延迟?
- 画布的大小
- 鱼的数量的位置计算
- 鱼的大小
- 平移,缩放,转换的计算
- 背景(鱼缸)
- …
结论
因为浏览器还没有提供通过JavaScript测量真正的FPS一种标准的方法, Web benchmarks测试出来的FPS本质上是不可信的(它可以测试SVG、Canvas、WebGL等渲染的FPS,而没法测试整个网页)。 Mozilla已经提供了一个方法来解决这个问题:mozPaintCount变量; 返回的次数文档已paint到屏幕的数目。理想情况下,我们会希望这个有待规范 ,使所有的现代浏览器将提供衡量FPS的标准接口。随着富媒体网站越来越多,保持FPS稳定的是很重要的事情, 在流畅的30帧运行的动画比跳动的50 FPS受欢迎得多。在webkit系列的浏览器中,解决这个问题的办法是公开一个webkitPaintCount变量。 我们可以通过webkitPaintCount的变化得到真正意义上的FPS.