You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chromium内核浏览器中requestAnimationFrame调用confirm后时间戳异常求助

Hey there! Let's break down this weird Chromium-specific issue you're facing with requestAnimationFrame (RAF) and modal dialogs, then fix it properly.

What's Going On Here?

When you trigger a confirm dialog before starting your RAF animation, Chromium (Chrome/Opera) behaves differently from Firefox/IE11. The problem boils down to:

  • The first timestamp passed to your animate function is actually the time the frame would have run if the dialog hadn't blocked the page.
  • When you click OK, the second timestamp is the actual current time. Their difference ends up being the full time you spent staring at the confirm dialog, which throws off your animation progress calculation entirely.

Firefox and IE11 handle this smarter—they pass the actual current time as the first timestamp once the dialog closes, so your animation works as expected. This feels like a Chromium bug (and it probably is), but until it's fixed, we can work around it.

The Fix: Use performance.now() Instead of RAF's Timestamp

The solution relies on performance.now(), a high-precision timer that's not affected by page blocking (like modal dialogs). It tracks the actual time elapsed since the page loaded, so it'll give us the correct start time for our animation, no matter how long the confirm dialog was open.

Here's your modified code with the fix:

const cache = { start: null, target: null };
function animate(timestamp) {
 console.log('RAF timestamp:', timestamp, '| Actual time:', performance.now());
 if (cache.start === null) {
   // Replace RAF's timestamp with performance.now() for our start time
   cache.start = performance.now();
 }
 // Calculate progress using the actual current time, not RAF's timestamp
 const progress = performance.now() - cache.start;
 cache.target.style.left = Math.min(progress / 10, 100) + 'px';
 
 if (progress < 1000) {
   requestAnimationFrame(animate);
 } else {
   cache.target.style.left = '0px';
   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>

Key Changes Explained

  1. Initializing the start time: Instead of using the first timestamp from RAF, we set cache.start to performance.now() when the animation first runs. This captures the exact moment the animation starts executing after the dialog closes.
  2. Calculating progress: We use performance.now() again to get the current time each frame, so the progress is always based on how long the animation has actually been running—ignoring any time spent blocked by the modal dialog.

Extra Notes

  • This workaround works across all browsers, not just Chromium, so it's safe to use universally.
  • If you want to push for a fix in Chromium, you can file a bug report in their issue tracker (search for existing issues first using keywords like requestAnimationFrame timestamp modal confirm—it's possible someone else has reported this already).

内容的提问来源于stack exchange,提问作者Andrei V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:15:50