【发布时间】: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() 方法告诉浏览器您希望执行动画,并请求浏览器调用指定函数以在下一次重绘之前更新动画。
这意味着浏览器一直在绘制,因此在每次重新绘制之前调用我的函数来记录消息。我猜浏览器会维护一个调度程序,该调度程序以与屏幕刷新率相匹配的速率进行绘制调用。
现在我的困惑在于以下几点:
- 浏览器的主线程是否不断地重新绘制、生成纹理并将纹理上传到 GPU 并进行绘制调用(被限制以匹配屏幕的刷新率)? (听起来效率低下)
- 这就是我的“onBeforeNextRepaint”回调被不断调用的原因吗?
- 如果 1 和 2 为真,在我第一次捕获时间线时,为什么我没有捕获“更新层树”和“复合层”事件?
【问题讨论】:
标签: javascript browser rendering requestanimationframe