requestAnimationFrame 在显示确认对话框时给出了错误的时间戳(Chromium?)

requestAnimationFrame gives the wrong timestamp when showing a confirm dialog (Chromium?)

我有一个简单的动画,它是使用 requestAnimationFrame 完成的(出于演示目的改编自 the example on MDN). If before the animation I show a confirm dialog, the timestamp received by the animation function is wrong. The difference between the first and second timestamps is equal to the time from the moment the confirm message was shown, until the "OK" button was clicked. This behaviour (bug?) is visible in Chrome and Opera (both running Chromium). Firefox and Internet Explorer 11 run as expected. Check the fiddle 或下面的示例。

const cache = {
  start: null,
  target: null
};

function animate(timestamp) {
  console.log(timestamp);
  if (cache.start === null) {
    cache.start = timestamp;
  }
  var progress = timestamp - cache.start;
  cache.target.style.left = Math.min(progress / 10, 100) + 'px';
  if (progress < 1000) {
    requestAnimationFrame(animate);
  } else {
    cache.target.style.left = 0;
    cache.start = null;
  }
}

(function() {
  const target = document.getElementsByTagName("div")[0];
  cache.target = target;
  const cb = document.getElementsByTagName("input")[0];

  const btn = document.getElementsByTagName("button")[0];
  btn.addEventListener("click", function() {
    if (cb.checked) {
      if (confirm("Just click 'OK' to start the animation, ok?")) {
        requestAnimationFrame(animate);
      }
    } else {
      requestAnimationFrame(animate);
    }
  })
})();
html,
body {
  padding: 0;
  margin: 0;
}

div {
  width: 50px;
  height: 50px;
  border: 1px solid black;
  background-color: yellowgreen;
  position: absolute;
  top: 50px;
}

button {
  margin-top: 20px;
}
<button type="button">Start</button>
<label>
  <input type="checkbox" />use "confirm"</label>
<div>

</div>

打开控制台查看收到的时间戳。动画设置为 运行 持续 2 秒。显示 confirm 对话框时,如果 "OK" 按钮的点击速度超过 2 秒,则动画 运行 秒 "remaining" 时间。如果点击 "OK" 按钮所需的时间比 time 动画时间长,元素将不会被动画化,并且会有 2 个值(时间戳)发送到控制台;这两个值的差异是单击 "OK" 按钮所需的时间。

我认为这是 Chromium 中的错误。是否有解决此问题的方法(仍然使用 requestAnimationFrame 进行动画处理,而不是通过 CSS 进行动画处理)?我在他们的跟踪器中找不到与此相关的任何信息。有人对此有更多信息吗?

不得不说,我发现这很有趣。

在花了很多时间之后,我可能已经为您找到了解决方法。你可以在这里看到。 https://jsfiddle.net/qtj467n0/13/

它的基本要点是,我用 performance.now() 替换了 requestAnimationFrame 提供的 DOMHighResTimeStamp,returns 和 DOMHighResTimeStamp

const cache = {
  start: null,
  target: null,
  time: 2000
};

function animate(timestamp) {
  console.log(timestamp);
  if (cache.start === null) {
    cache.start = timestamp;
  }
  var progress = timestamp - cache.start;
  cache.target.style.left = Math.min(progress / 10, cache.time / 10) + 'px';
  if (progress < cache.time) {
    requestAnimationFrame(animate);
  } else {
    cache.target.style.left = 0;
    cache.start = null;
  }
}

const render = () => {

  requestAnimationFrame((timestamp) => {

    const performanceNow = performance.now();

    animate(performanceNow)
  });
}

(function() {
  const target = document.getElementsByTagName("div")[0];
  cache.target = target;
  const cb = document.getElementsByTagName("input")[0];


  const btn = document.getElementsByTagName("button")[0];
  btn.addEventListener("click", function() {
    if (cb.checked) {
      const confirmed = confirm("Just click 'OK' to start the animation, ok?");
      if (confirmed) {
        render();
      }
    } else {
      requestAnimationFrame(animate);
    }
  })
})();
html,
body {
  padding: 0;
  margin: 0;
}

div {
  width: 50px;
  height: 50px;
  border: 1px solid black;
  background-color: yellowgreen;
  position: absolute;
  top: 50px;
}

button {
  margin-top: 20px;
}
<button type="button">Start</button>
<label>
  <input type="checkbox" />use "confirm"</label>
<div>

</div>