是否有可能找出javascript中的监视器帧速率是多少?

时间:2011-05-25 21:17:03

标签: javascript

  1. 首先,是否有可能找到答案 什么是监视器帧/刷新率 javascript(大多数液晶显示器为60Hz)?
  2. 第二,有什么办法吗? 说之后执行一个函数 每X帧?
  3. 有几个人问我为什么需要这个。这是上下文:我有一个动画(一个接一个渲染一个帧的无限循环)。每次迭代的输出需要与监视器刷新率同步,否则将发生tearing。我现在这样做的方法是在setTimeout(loop, 16)方法中使用loop。它的工作。第二个参数需要是1 /(刷新率),这就是我问这个问题的原因。

5 个答案:

答案 0 :(得分:11)

现代浏览器使用window.requestAnimationFrame可能会有一些运气,其中有一个简单的回调来衡量连续调用之间的时间以及计算FPS的时间。

您还应该能够在每次调用时轻松跳过渲染功能,以降低所需的帧速率。

我在http://jsfiddle.net/rBGPk/做了一个粗略的例子 - 数学可能有点错误,但它应该足以表明一般的想法。

答案 1 :(得分:4)

以下解决方案的工作原理是测量两个连续动画帧之间的毫秒数。

警告:它通常会返回不正确的FPS,因为当您的CPU忙于执行其他任务时,有时会跳过动画帧。



Master




<强>提示

答案 2 :(得分:0)

这是一种强大的方法,使用requestAnimationFrame方法。

function calcFPS(opts){
    var requestFrame = window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame;
    if (!requestFrame) return true; // Check if "true" is returned; 
                                    // pick default FPS, show error, etc...
    function checker(){
        if (index--) requestFrame(checker);
        else {
            // var result = 3*Math.round(count*1000/3/(performance.now()-start));
            var result = count*1000/(performance.now()- start);
            if (typeof opts.callback === "function") opts.callback(result);
            console.log("Calculated: "+result+" frames per second");
        }
    }
    if (!opts) opts = {};
    var count = opts.count||60, index = count, start = performance.now();
    checker();
}

count的值越高,FPS的值越准确,FPS测试的时间就越长。

可以使用额外的逻辑来舍入到15 / 12s,即24​​,30,48,60 120 ... FPS。

这是编译版本(四舍五入到3 FPS):

function calcFPS(a){function b(){if(f--)c(b);else{var e=3*Math.round(1E3*d/3/(performance.now()-g));"function"===typeof a.callback&&a.callback(e);console.log("Calculated: "+e+" frames per second")}}var c=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;if(!c)return!0;a||(a={});var d=a.count||60,f=d,g=performance.now();b()}

像这样使用:

calcFPS(); // Only logs to console (you can remove the console log,
           // making this call redundant)

calcFPS({count: 30}); // Manually set count (the test should take 500ms
                      // on a 60FPS monitor

calcFPS({callback: useFPS}); // Specify a callback so you can use the
                             // FPS number value

var FPS = 0, err = calcFPS({count: 120, callback: fps => FPS = fps});
if (err) FPS = 30; 

答案 3 :(得分:0)

计算重绘之间的时间间隔:

const getRepaintInterval = () => {
  return new Promise((resolve) => {
    requestAnimationFrame((t1) => {
      requestAnimationFrame((t2) => {
        resolve(t2 - t1);
      });
    });
  });
};

或者计算选定秒内的FPS:

const getFps = () => new Promise(resolve => {
    let repaint = 0;
    const start = performance.now();
    const withRepaint = () => {
        requestAnimationFrame(() => {
            if ((performance.now() - start) < 1000) {
                repaint += 1;
                withRepaint();
            } else {
                resolve(repaint);
            }
        });
    };
    withRepaint();
});

或使用 startend 计算 FPS:

const fpsHandler = () => {
    let repaint;
    let stop;
    let ret;
    let start;
    const init = () => {
        ret = undefined;
        stop = false;
        repaint = 0;
        start = performance.now();
    };
    init();
    const withRepaint = () => {
        requestAnimationFrame(() => {
            if (!stop) {
                repaint += 1;
                withRepaint();
            }
        });
    };
    return {
        start: () => {
            init();
            withRepaint();
        },
        end: () => {
            stop = true;
            if (!ret) ret = repaint / ((performance.now() - start) / 1000);
            return ret;
        }
    }
};

const { start, end } = fpsHandler();

答案 4 :(得分:0)

根据之前解释使用 requestAnimationFrame 并测量帧之间的时间差的一些答案,这里是一个使用 requestAnimationFrame 和已发送到回调的时间戳的解决方案。否则就没有理由运行单独的 performance.now() 函数。

var previousTimestamp, divInterval, divFPS;

const raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;

const rafLoop = timestamp => {
    let interval = timestamp - previousTimestamp;
    let fps = 1000 / interval;
    divInterval.innerHTML = `Interval: ${interval}`;
    divFPS.innerHTML = `FPS: ${fps}`;
    previousTimestamp = timestamp;
    raf(rafLoop);
};

divInterval = document.getElementById('interval');
divFPS = document.getElementById('fps');

// This is run first to set the previousTimestamp variable with an initial value, and then call the rafLoop function.
raf(timestamp => {
    previousTimestamp = timestamp;
    raf(rafLoop);
});
<div id="interval"></div>
<div id="fps"></div>

另请参阅 https://codepen.io/sassano/pen/wvgxxMp 以获取此代码段源自的带有动画的另一个示例。