cancelAnimationFrame是否清除任何现有的requestAnimationFrame队列?

huangapple go评论52阅读模式
英文:

Does cancelAnimationFrame clear any existing requestAnimationFrame queues?

问题

cancelAnimationFrame是否完全移除了所有排队的动画逻辑?例如,假设逻辑很复杂,我的屏幕以60FPS运行。完成每一帧的整个逻辑所需的时间,假设是50毫秒。这比维持60FPS所需的最小值16.66667毫秒要多得多。如果每帧花费50毫秒,在60帧的总数中,将会积累动画逻辑队列,对吗?通常情况下,在60fps下,使用60帧,整个动画应该花费1秒。对吗?但是使用我的动画逻辑,将需要总共3秒才能完成动画。

假设,在我在t0开始动画后,等待动画进行到t1.5,然后运行cancelAnimationFrame函数,它会立即停止动画吗?还是会一直进行,直到过了3秒才停止?

如果我在t0.5时运行cancelAnimationFrame函数会怎样?它会立即停止动画吗?还是会完成一半的动画,直到过了1.5秒才停止?

对于未来阅读此内容的人们的后续编辑:
是的。cancelAnimationFrame确实会在调用时立即停止动画。对上述两个假设性问题的答案都是肯定的。

英文:

Does cancelAnimationFrame completely removes all the queued up animation logic?
For example, lets say the logic was complicated and my screen was doing 60FPS. the time it took to complete the entire logic per frame, lets say is 50ms. That is much more than 16.66667ms which is the minimum to maintain 60FPS.
If each frame takes 50ms in a total of 60 frames, there would be a build up of the animation logic queue. right?
Normally, at 60fps, with 60 frames, the entire animation should take 1 second. Right?
But with my animation logic, it will take 3 seconds total to complete the animation.

Let's assume, after I start the animation at t0, and I wait until t1.5 while animation is ongoing, and I run the cancelAnimationFrame function, will it stop the animation right then and there? Or will it complete the entire animation until 3 seconds have passed?

What about if I run the cancelAnimationFrame function at t0.5? will it stop the animation right then and there? Or will it complete halfway of the animation until 1.5 seconds have passed?

follow up edit for people reading this in the future:
yes. cancelAnimationFrame does indeed stop the animation immediately as it is called. Yes to both of the above hypothetical questions.

答案1

得分: 2

cancelAnimationFrame(id) 不会停止任何东西。

它的作用是从动画帧回调列表中删除与传递的id相对应的排队回调,因此仅此回调永远不会被调用。
但是,如果在调用cancelAnimationFrame(id)时回调已经被执行,或者在执行回调时调用了它,那么它将是一个无操作:什么也不会发生。

你可以看到,即使在调用cancelAnimationFrame()之后,回调仍然继续执行:

const id = requestAnimationFrame(() => {
  // 当执行此回调时,它已从动画帧回调列表中删除
  cancelAnimationFrame(id); // 无操作
  // 回调没有停止,并且继续执行其原本的任务。
  console.log("仍在运行");
});

cancelAnimationFrame(id) 在以下情境中才有意义:要么你想要完全停止依赖于requestAnimationFrame()的动画循环,从外部来控制,要么你想要取消一次性回调,再次是从外部来控制。从回调本身来说,它是无用的,如果你不想继续循环,那么就不要从该回调中再次调用requestAnimationFrame()

关于你担心队列溢出的问题,这不会发生。当你调用requestAnimationFrame(callback)时,它实际上是告诉浏览器:“下一次你传递数据给合成器时,在那之前执行这个操作”。如果你在该回调中再次调用requestAnimationFrame(callback),浏览器将理解它必须等待下一个绘制帧,如果你阻塞了引擎足够长的时间,可能确实会在几个监视器的刷新间隔之后,但这并不重要,它仍然是浏览器的下一个绘制帧。因此,你的循环永远不会在一个绘制帧中排队超过一个回调,浏览器仍然有时间渲染并执行其任务,在这之间,你可能会浪费一些监视器刷新,可能会有一些不流畅的动画,但你不会使动画帧队列溢出。

英文:

No cancelAnimationFrame(id) doesn't stop anything.

What it does is it removes the queued callback corresponding to the passed id from the list of animation frame callbacks, so that this callback (and only this one) is never called.
However if the callback has already been executed, or if it's being executed, when cancelAnimationFrame(id) is called, then it's a no-op: nothing is done.

You can see how the callback keeps being executed even after it called cancelAnimationFrame():

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const id = requestAnimationFrame(() =&gt; {
  // When this callback is executed, it has already been removed
  // from the list of animation frame callbacks.
  cancelAnimationFrame(id); // no-op
  // The callback isn&#39;t stopped and continues to do whatever it was supposed to do.
  console.log(&quot;still running&quot;);
});

<!-- end snippet -->

cancelAnimationFrame(id) makes sense in a context where you either want to stop entirely an animation loop relying on requestAnimationFrame(), from the outside, or if you want to cancel a one-shot callback, once again from the outside. From the loop itself it's useless, if you don't want to continue the loop, then don't call requestAnimationFrame() again from that callback.

Regarding your fear of overflowing the queue, this won't happen. when you call requestAnimationFrame(callback) what it really does is to tell the browser "The next time you will pass data to the compositor, execute that right before.". If you do call requestAnimationFrame(callback) in that callback, the browser will understand it has to wait for yet the next painting frame, which if you block the engine long enough may indeed be a few monitor's refresh ticks later, but that doesn't matter, it will still be the browser's next painting frame. So your loop will never queue more than one callback per painting frame, the browser will still have time to render and do its things in between, and while you will waste some monitor refreshes, and probably have a junky animation, you won't overflow the animation frames queue.

huangapple
  • 本文由 发表于 2023年7月18日 01:57:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76707017.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定