javascript - 请求不断调用的动画帧

标签 javascript browser rendering requestanimationframe

尝试了解 RequestAnimationFrame 及其内部工作原理。

浏览器有一个主线程,它是一个事件循环。事件循环可以填充各种异步事件,例如用户交互、定时器被触发、网络调用完成以及触发布局和绘制的事件,例如输入或JS。

因此,当 JS 函数使 DOM 布局无效或导致重新绘制时,浏览器的主线程重新绘制需要更新的图层,合成器线程将更新后的纹理上传到 GPU,最终合成发生并显示结果图像到屏幕上。

因此,我的印象是浏览器仅在实际需要时才执行绘制。如果您在静态页面上捕获 Chrome Dev Tools 时间轴上的事件而没有发生任何事情,则绝对不会捕获任何事件(没有布局、没有绘制、没有触发动画帧)。说得通。

然后你在控制台上运行下面的代码,

function onBeforeNextRepaint() {
    requestAnimationFrame(onBeforeNextRepaint);

    console.log('About to paint ...');
}

onBeforeNextRepaint();

现在,您再次捕获时间轴事件,您注意到“动画帧已触发”事件,并且您的控制台被记录为“即将绘制...”。

onBeforeNextRepaint gets called

Animation Frame Fired invoked

根据 MDN ,

The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint.

这意味着浏览器一直在绘制,因此在每次重新绘制之前调用我的函数来记录消息。我猜浏览器会维护一个调度程序,该调度程序会以与屏幕刷新率相匹配的速率进行绘制调用。

现在我的困惑在于以下几点:

  1. 浏览器的主线程是否不断地重新绘制、生成纹理并将纹理上传到 GPU 并进行绘制调用(节流以匹配屏幕的刷新率)? (听起来效率低下)
  2. 这就是我的“onBeforeNextRepaint”回调不断被调用的原因吗?
  3. 如果 1 和 2 为真,在我的第一次时间线捕获中,为什么我不捕获“更新层树”和“复合层”事件?

最佳答案

以下blog post真的帮助我理解了整个事情是如何运作的。

来自它:

从本质上讲,整个事件循环功能可以用这段代码来说明:

while (eventLoop.waitForTask()) {  
    const taskQueue = eventLoop.selectTaskQueue()
    if (taskQueue.hasNextTask()) {
        taskQueue.processNextTask()
    }

    const microtaskQueue = eventLoop.microTaskQueue
    while (microtaskQueue.hasNextMicrotask()) {
        microtaskQueue.processNextMicrotask()
    }

    if (shouldRender()) {
        applyScrollResizeAndCSS()
        runAnimationFrames()
        render()
    }
}

然后这样描绘:

A diagram showing the task/microtask/and animationframe queue

关于javascript - 请求不断调用的动画帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28649766/

相关文章:

c# - C#中如何在WebBrowser控件中加载本地HTML页面

Android TextView 顶部图像无法在 2.3 上正确呈现

java - LibGDX:如何在 FreetypeFont 中添加渐变颜色?

javascript - 设置 reCAPTCHA Version 2 设置英语以外的另一种语言

javascript - Meteor 出版物和订阅

javascript - 有没有理由在 Internet Explorer 中用 Script 替换 JavaScript?

CSS - 最大 z-index 值

spring-mvc - 防止用户在 spring `Web application` 中使用浏览器后退按钮返回

javascript - Javascript 图像交换上的 CSS 过渡

css - 改变浏览器与 css 和 dom 的交互