perfomance.now()在requestAnimationFrame之前被调用 - performance.now()具有较大的时间戳

4

所以我有一个简单的函数:

var start = function(){

    lastFrame = performance.now();


    requestAnimationFrame((t)=>{interval(t)});


}

我的间隔函数(仅用于测试目的,我已经阻塞了每个rAF时间戳的值)

function interval(t){
    console.log (t);
    console.log(lastFrame);
}

我已经阅读了对另一个问题的以下回答,但是有几个部分我就是不理解这个人的回答。

传递给requestAnimationFrame()回调的时间戳是动画帧开始的时间。在同一帧期间调用多个回调函数会接收相同的时间戳。因此,如果performance.now()返回先于参数值的时间,这将非常奇怪,但如果返回稍后的时间则不会很奇怪。

"如果performance.now()返回先于参数值的时间,这将非常奇怪"?

为什么这会很奇怪呢?我认为Javascript是一种解释型语言?此时:

lastFrame = performance.now();

浏览器甚至不知道下一行的存在:
requestAnimationFrame((t)=>{interval(t)});

当你在为requestAnimationFrame提供回调函数之前调用performance.now(),那么lastFrame的时间应该小于传递给requestAnimationFrame的t时间。在这个人的回复中,他列出了请求动画帧所涉及的6个步骤。然而,他将performance.now()调用列为最后一步。但它在动画帧请求之前被浏览器解释,怎么可能是最后一步呢?

他正在谈论从“interval”函数内部调用performance.now,而不是从“start”中调用。 - Bergi
2个回答

3
我也遇到过这个问题。由于这个问题非常不符合直觉,所以看起来像一个错误。
我已经采用了 Date.now() 作为 elapsedTime 的初始值。
var elapsedTime = 0;
var startTime = Date.now();
var lastTime = null;

requestAnimationFrame(update);

function update(currentTime) {
  if (lastTime) {
    elapsedTime += currentTime - lastTime;
  } else {
    elapsedTime = Date.now() - startTime;
  }

  // Compute the next value in the animation.
  var value = computeValue(elapsedTime);

  // Store the timestamp representing the animation frame.
  lastTime = currentTime;
}

3

你所指向的答案谈到了在rAF回调函数内部调用performance.now()函数。而你是在外部调用,因此它返回的时间自然要早于期望。


简化后的代码:

let t0 = performance.now(); // This is called now

requestAnimationFrame(t1=>func(t1)); // this will be called at next screen refresh
                                     // (somewhere between 0 and 17 ms later)

另一个回答的要点:y
let f1 = time => {
  window.calledTime = time;
  while(wait(a_few_seconds)){}
  }
let f2 = time => {
  time === window.calledTime; // true !
  performance.now() - time; // approximately a_few_seconds
  }
requestAnimationFrame(f1);
requestAnimationFrame(f2);

所以简单来说,在您的情况下,lastFramet之前被设置是正常的,因为它在之前被称为way(rAF是异步的)。另一个答案谈到了链接的rAF调用,它们都堆叠在同一个函数调用中,因此无论先前回调需要多长时间来执行,它们都将共享相同的时间戳参数。
现在,如果您需要原始时间戳,可以放心使用performance.now()作为后备,因为它类似于发送到回调函数的参数,除了它反映监视器发送其最后V-Sync脉冲的时间,并且因此适用于同一帧的所有回调。
const loop = time => { 
  if(!time) time = performance.now(); // we called it out of a rAF routine
  ...
  requestAnimationFrame(loop)
}
loop();

然而,如果你正在使用rAF循环,大多数情况下是因为你需要让你的例程与屏幕同步。因此,在开始你的循环之前等待下一次屏幕刷新更有意义,否则你将在一个帧中执行两次该例程。

const loop = time =>{
    ...
  }
requestAnimationFrame(loop); // call it directly through rAF

你好,你知道这个问题的答案吗?http://stackoverflow.com/questions/43696831/d3-force-directed-graph-why-dont-the-flags-appear - Coder1000
你没有回答“如果在为requestAnimationFrame提供回调之前调用performance.now(),那么lastFrame的时间应该小于传递给requestAnimationFrame的t吗?” - Changdae Park
1
@ChangdaePark 我不需要这样做,因为 OP 误读了他们链接到的另一个答案。他们没有理解为什么另一个回答者说这会很奇怪,因为他们错过了它们处于完全不同的配置中。这个问题与 rAF 时间戳可能设置为实际调用之前的时间戳无关(至少在 Chrome 中有缺陷的实现中)。我认为你已经看到了处理这种情况的一个问题:https://stackoverflow.com/questions/64177381/timestamp-of-requestanimationframe-is-not-reliable/64289656#64289656 - Kaiido

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接