我有一个简单的动画,使用requestAnimationFrame
完成(为了演示目的改编自the example on MDN)。如果在动画之前我显示了confirm
对话框,则动画函数接收的时间戳是错误的。第一个和第二个时间戳之间的差异等于从显示confirm
消息的那一刻起,直到单击“确定”按钮为止。这种行为(错误?)在Chrome和Opera中都可见(两者都运行Chromium)。 Firefox和Internet Explorer 11按预期运行。检查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
对话框时,如果单击“确定”按钮的时间超过2秒,则动画将运行“剩余”时间。如果单击“确定”按钮所需的时间比动画时间长,则元素将不会被动画,并且将有2个值(时间戳)发送到控制台;这两个值的差异是单击“确定”按钮所需的时间。
我认为这是Chromium中的一个错误。有没有解决方法(仍然使用requestAnimationFrame
动画,而不是通过CSS)?我在他们的追踪器中找不到任何相关内容。有没有人有这方面的其他信息?
我不得不说,我发现这非常有趣。
花了很多时间后,我可能已经为你找到了解决方法。你可以在这看到。 https://jsfiddle.net/qtj467n0/13/
它的基本要点是,我取代了DOMHighResTimeStamp
提供的requestAnimationFrame
和performance.now()
,它也返回了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>