当前位置: 首页 > 科技观察

JS模拟监控页面

时间:2023-03-19 20:54:41 科技观察

动画的FPS帧率其实是由图片一帧一帧组成的。如果有网页动画,播放时会有动画的帧率。在不同设备上的不同条件下,帧率是不同的。有时候,对于一些复杂的SVGA或者CSS动画,我们需要实时监控它们的帧率,或者了解它们在不同设备上的运行状态,以便更好地优化它们。流畅度的标准首先,澄清一些概念。FPS表示每秒更新图片的次数。我们平时看到的连续画面是由静止画面组成的,每幅画面称为一帧,而FPS是描述“帧”变化快慢的物理量。从理论上讲,FPS越高,动画就越流畅。目前大部分设备的屏幕刷新率都是每秒60次,所以一般来说,FPS为60帧/秒时动画效果最好,也就是每帧消耗的时间为(1000/60)16.67毫秒。当然,经常玩FPS游戏的朋友肯定知道,小鸡/CSGO等FPS游戏推荐使用刷新率为144HZ的显示器,而144Hz显示器特指刷新率为144Hz的显示器。第二。相比普通显示器每秒60次的刷新率,画面显示更加流畅。因此,144Hz的显示器更适合视角经常保持高速移动的第一人称射击游戏。但是,这只是显示器提供的高刷新率功能。对于我们的网页动画,是否支持取决于浏览器,大多数浏览器的刷新率都是每秒60次。直观感受,不同帧率的体验:帧率为50-60FPS的动画会相当流畅,让人感觉更舒服;30-50FPS帧率的动画会舒服,因为每个人的敏感度不同动画的程度因人而异;帧率低于30FPS的动画会让人有明显的卡顿和不适感;帧率波动较大的动画也会让人有卡顿的感觉。那么我们如何通过JS模拟获取我们页面动画当前的FPS值呢?requestAnimationFramerequestAnimationFrame大家应该不陌生。该方法告诉浏览器你要执行动画,并请求浏览器在下次重绘之前调用指定的函数来更新动画。//语法window.requestAnimationFrame(callback);当您准备好更新屏幕时,您可以使用此方法。这将要求您的动画功能在浏览器的下一次重绘之前执行。回调次数通常为每秒60次,大多数浏览器通常匹配W3C推荐的刷新率。使用requestAnimationFrame计算FPS的原理原理是,正常情况下,requestAnimationFrame方法一秒会执行60次,即不掉帧。假设动画在时间A开始,在时间B结束,耗时x毫秒。而中间的requestAnimationFrame一共执行了n次,所以这个动画的帧率大致为:n/(B-A)。核心代码如下,可以近似每秒的页面帧率,另外我们额外记录一个allFrameCount来记录rAF的执行次数,计算每个动画的帧率:varrAF=function(){return(window.requestAnimationFrame||window.webkitRequestAnimationFrame||function(callback){window.setTimeout(callback,1000/60);});}();varframe=0;varallFrameCount=0;varlastTime=Date.now();varlastFameTime=Date。now();varloop=function(){varnow=Date.now();varfs=(now-lastFameTime);varfps=Math.round(1000/fs);lastFameTime=now;//不设置0,在动画的开头和结尾,记录这个值的差,计算FPSallFrameCount++;frame++;if(now>1000+lastTime){varfps=Math.round((frame*1000)/(now-lastTime));console.log(`${newDate()}FPSwithin1S:`,fps);frame=0;lastTime=now;};rAF(loop);}loop();如果我们需要统计某个特定动画过程的帧率,我们只需要在动画开始和结束两处记录allFrameCount的值,然后除以中间花费的时间,就得到特定的FPS值也可以获得动画过程。值得注意的是,该方法的计算结果与实际帧率肯定存在误差,因为它是将主线程每两次执行javascript的时间间隔视为一帧,而不是上面提到的主线程加上合成线程。消耗的时间是一帧。但在这个阶段,它被认为是一种可取的方法。适当美化importBUSfrom'event-bus';//计算性能指标(()=>{constcreateConsole=(desc,val)=>console.log(`%c${desc}`,'color:#fff;background:red;padding:2px6px;border-radius:3px;',val);window.addEventListener('load',()=>{consttiming=performance.timing;createConsole('DNS解析耗时',timing.domainLookupEnd-timing.domainLookupStart);createConsole('TCP连接耗时',timing.connectEnd-timing.connectStart);createConsole('网络请求耗时',timing.responseStart-timing.requestStart);createConsole('数据传输时间-consuming',timing.responseEnd-timing.requestStart);createConsole('页面首次渲染时间',timing.responseEnd-timing.navigationStart);createConsole('首次交互时间',timing.domInteractive-timing.navigationStart);createConsole('DOM解析耗时',timing.domInteractive-timing.responseEnd);createConsole('DOM构建耗时',timing.domComplete-timing.domInteractive);createConsole('HTML加载完成,DOMReady',timing.domContentLoadedEventEnd-timing.navigationStart);createConsole('页面完全加载耗时',timing.loadEventStart-timing.navigationStart);});})();//FPS检测(()=>;{constlimit=3;//连续低FPS的上限constbelow=20;//可容忍的最低FPSconstupdateInterval=2*1000;//检测帧率的间隔时间letupdateTimer=0;//经过的时间letcount=0;letlastTime=performance.now();letframe=0;letlastFameTime=performance.now();constloop=()=>{frame+=1;constnow=performance.now();constfs=(now-lastFameTime);lastFameTime=now;updateTimer+=fs||0;if(updateTimer1000+lastTime){fps=Math.round((frame*1000)/(now-lastTime));frame=0;lastTime=now;}if(fps=limit){console.log('网页卡住',`${count}次连续FPS低于${below},当前FPS为${fps}`);BUS.trigger('fps-low');//关闭一些JS动画}}else{count=0;}window.requestAnimationFrame(loop);};loop();})();参考Web动画帧率(FPS)计算:https://www.cnblogs。com/coco1s/p/8029582.html