取消动画超时后的帧



Id 就像一个基于 requestAnimationFrame 的动画循环,在 x ms 后停止。我试图通过一个 setTimeout 来实现这一点,该 setTime 会在 x 之后删除 cb。但是,由于 setTimeout 是事件循环中调用的最后一件事,因此有时会在调用删除之前再渲染一帧动画。

即使增量(它应该已经取消但不是(总是非常小,这搞砸了我的迭代逻辑。调用的最后一个动画帧必须在给定的时间帧 x 内。

如果已超过最大值,我真的很想检查每个循环。

是否有某种高优先级设置超时?也许是基于承诺?

setTimeout并不是在事件循环中最后被调用的东西,恰恰相反,实际上,在事件循环模型中,运行动画帧回调是最后被调用的东西之一。

所以我不确定你做了什么,但使用setTimeout应该可以正常工作:

let stopped = false;
const startTime = performance.now();
let rafTime;
let frame_id = requestAnimationFrame( loop );
setTimeout(() => {
cancelAnimationFrame(frame_id);
stopped = true;
console.log( 'stopped' );
console.log( "rAF loop ran for %sms", rafTime - startTime );
}, 2000);
function loop() {
if( stopped ) { console.log( 'failed' ); }
rafTime = performance.now();
frame_id = requestAnimationFrame( loop );
}

另一个解决方案,就像您在 rAF 中所做的工作可能需要增量时间一样好,那就是检查传递给回调的时间戳。这是一个非常快速的操作,根本不用担心这里的性能。

let startTime;
requestAnimationFrame( loop );
function loop( time ) {
if( !startTime ) { startTime = time; }
if( time - startTime >= 2000 ) {
console.log( 'ran for %sms', time - startTime )
return;
}
requestAnimationFrame( loop );
}

关于这种方法的一件事是,你以后会知道时间流逝了,这意味着你可能会晚一帧。
您可以尝试自己从持续时间中减去帧率,但 rAF 率取决于显示器的刷新率,因此很难计算。

但这也可能是一个优势,因为您还可以执行最后一帧渲染,这在执行动画时通常很有用,以便最终调用在精确的静态位置绘制。

现在请注意,Chrome 调用 rAF 的方式存在已知问题,也许您的代码因为类似的事情而中断,也许它因为其他逻辑而中断,但没有您的代码,我们只能说它应该可以工作

最新更新