HTML5技术

【前端性能】Web 动画帧率(FPS)计算 - ChokCoco(2)

字号+ 作者:H5之家 来源:H5之家 2017-12-14 14:04 我要评论( )

var observer = new PerformanceObserver(function(list) {var perfEntries = list.getEntries();for (var i = 0; i perfEntries.length; i++) {console.log("frame: ", perfEntries[i]);}});// subscribe to Frame

var observer = new PerformanceObserver(function(list) { var perfEntries = list.getEntries(); for (var i = 0; i < perfEntries.length; i++) { console.log("frame: ", perfEntries[i]); } }); // subscribe to Frame Timing observer.observe({entryTypes: ['frame']});

每条记录包含的信息基本如下:

{ sourceFrameNumber: 120, startTime: 1342.549374253 cpuTime: 6.454313323 }

每个记录都包括唯一的 Frame Number、Frame 开始时间以及 cpuTime 时间。通过计算每一条记录的 startTime ,我们就可以算出每两帧间的间隔,从而得到动画的帧率是否能够达到 60 FPS。

不过!看看 Web Performance Timing API 整体的兼容性:

image

Frame Timing API 虽好,但是,现在 Frame Timing API 的兼容性不算很友好,额,不友好到什么程度呢。还没有任何浏览器支持,处于实验性阶段,属于面向未来编程。这你 TM 逗我呢?说了这么久完全不能用.....

xx

  法三:借助 requestAnimationFrame API

费了这么多笔墨描述 Frame Timing API 但最后因为兼容性问题完全没办法使用。不过不代表这么长篇幅的描述没有用,从上面的介绍,我们得知,如果我们可以到得到每一帧中的固定一个时间点,那么两者相减,也能够近似得到一帧所消耗的时间。

那么,我们再另辟蹊径。这次,我们借助兼容性不错的 requestAnimationFrame API。

// 语法 window.requestAnimationFrame(callback);

requestAnimationFrame 大家应该都不陌生,方法告诉浏览器您希望执行动画并请求浏览器调用指定的函数在下一次重绘之前更新动画。

当你准备好更新屏幕画面时你就应用此方法。这会要求你的动画函数在浏览器下次重绘前执行。回调的次数常是每秒 60 次,大多数浏览器通常匹配 W3C 所建议的刷新率。

  使用 requestAnimationFrame 计算 FPS 原理

原理是,正常而言 requestAnimationFrame 这个方法在一秒内会执行 60 次,也就是不掉帧的情况下。假设动画在时间 A 开始执行,在时间 B 结束,耗时 x ms。而中间 requestAnimationFrame 一共执行了 n 次,则此段动画的帧率大致为:n / (B - A)。

核心代码如下,能近似计算每秒页面帧率,以及我们额外记录一个 allFrameCount,用于记录 rAF 的执行次数,用于计算每次动画的帧率 :

var rAF = function () { return ( window.requestAnimationFrame || window.webkitRequestAnimationFrame || function (callback) { window.setTimeout(callback, 1000 / 60); } ); }(); var frame = 0; var allFrameCount = 0; var lastTime = Date.now(); var lastFameTime = Date.now(); var loop = function () { var now = Date.now(); var fs = (now - lastFameTime); var fps = Math.round(1000 / fs); lastFameTime = now; // 不置 0,在动画的开头及结尾记录此值的差值算出 FPS allFrameCount++; frame++; if (now > 1000 + lastTime) { var fps = Math.round((frame * 1000) / (now - lastTime)); console.log(`${new Date()} 1S内 FPS:`, fps); frame = 0; lastTime = now; }; rAF(loop); } loop();

OK,寻找一个有动画不断运行的页面进行测试,可以看到代码运行如下:

image

这里,我使用了我之前制作的一个页面进行了测试,使用 Chrome 同时调出页面的 FPS meter,对比两边的实时 FPS 值,基本吻合。

测试页面,Solar System。你可以将上面的代码贴到这个页面的 console 中,测试一下数据:

framefps

对比右上角的 Frame Rate,帧率基本一致。在大部分情况下,这种方法可以很好的得出 Web 动画的帧率。

如果我们需要统计某个特定动画过程的帧率,只需要在动画开始和结尾两处分别记录 allFrameCount 这个数值大小,再除以中间消耗的时间,也可以得出特定动画过程的 FPS 值。

值得注意的是,这个方法计算的结果和真实的帧率肯定是存在误差的,因为它是将每两次主线程执行 javascript 的时间间隔当成一帧,而非上面说的主线程加合成线程所消耗的时间为一帧。但是对于现阶段而言,算是一种可取的方法。

  参考文章

 

好了,本文到此结束,希望对你有帮助 :)

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 移动前端图片压缩上传 - 李某龙

    移动前端图片压缩上传 - 李某龙

    2017-12-06 08:12

  • 高性能、高可用、高扩展、分布式ERP系统架构设计 - 刘彻

    高性能、高可用、高扩展、分布式ERP系统架构设计 - 刘彻

    2017-12-03 15:03

  • canvas动画3:交互 - dkplus

    canvas动画3:交互 - dkplus

    2017-11-24 13:05

  • vue+element-ui实现分页 - WEB前端小菜鸟

    vue+element-ui实现分页 - WEB前端小菜鸟

    2017-11-23 14:05

网友点评