【问题标题】:Request animation frame called constantly请求动画帧不断调用
【发布时间】:2015-04-23 08:36:54
【问题描述】:

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

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

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

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

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

function onBeforeNextRepaint() {
    requestAnimationFrame(onBeforeNextRepaint);

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

onBeforeNextRepaint();

现在,您再次捕获时间线事件,并注意到“Animation Frame Fired”事件,并且您的控制台记录了“About to paint ...”。

根据MDN

Window.requestAnimationFrame() 方法告诉浏览器您希望执行动画,并请求浏览器调用指定函数以在下一次重绘之前更新动画。

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

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

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

【问题讨论】:

    标签: javascript browser rendering requestanimationframe


    【解决方案1】:

    以下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()
        }
    }
    

    然后像这样描绘:

    【讨论】:

    • 刚刚阅读这个答案。感谢您链接到那篇很棒的帖子和您的回答。
    【解决方案2】:

    我认为您误解了 MDN 给出的描述。让我分解一下。

    Window.requestAnimationFrame() 方法告诉浏览器您希望执行动画

    这意味着它将告诉浏览器您希望执行需要重新绘制的动画。但要做到这一点,我们需要运行一些代码。

    并请求浏览器在下一次重绘之前调用指定的函数来更新动画。

    这意味着就在动画需要的下一次重绘之前,调用我的回调函数。

    requestAnimationFrame 不是绘画事件回调,而是一种在浏览器现在必须执行的下一次绘画之前触发回调的方法。

    【讨论】:

    • 谢谢亚历山大,你的回答有帮助。我也想得到其他意见,所以我会等我接受最终答案:)
    猜你喜欢
    • 2012-12-27
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多