Trying to understand RequestAnimationFrame and how it works internally.
Browser has a main thread which is an event loop. The event loop can be populated with various asynchronous events like user interaction, timers getting fired, network calls completing and events triggering layout and painting e.g. input or JS.
So, when a JS function invalidates the layout of the DOM or causes repaint, the browser's main thread repaints the layers that need updating and the compositor thread uploads the updated textures to the GPU where final compositing occurs and the resulting image is displayed onto the screen.
So, I have the impression that browsers only perform paint when actually required. If you capture events on Chrome Dev Tools timeline on a static page with nothing happening, absolutely no events are captured (no layout, no paint, no animation frame fired). Makes sense.
But then you run the following code on the console,
function onBeforeNextRepaint() {
requestAnimationFrame(onBeforeNextRepaint);
console.log('About to paint ...');
}
onBeforeNextRepaint();
Now, you capture the timeline events again and you notice the 'Animation Frame Fired' events and your console gets logged with 'About to paint ...'.
According to 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.
That means the browser is constantly painting and therefore calling my function to log the message before each repaint. I am guessing the browsers maintain a scheduler that makes the paint calls at the rate that matches the refresh rate of the screen.
Now my confusion lies on the following:
The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden <iframe> s in order to improve performance and battery life.
To optimize system and browser resources, it is recommended to use requestAnimationFrame , which requests the browser to execute the code during the next repaint cycle. This allows the system to optimize resources and frame-rate to reduce unnecessary reflow/repaint calls.
The frame is a single image in a sequence of pictures. In general, one second of a video is comprised of 24 or 30 frames per second also known as FPS. The frame is a combination of the image and the time of the image when exposed to the view. An extract of frames in a row makes the animation.
If you assign your requestAnimationFrame() method to a variable, you can use the cancelAnimationFrame() method to cancel it before it runs.
I think you are misunderstanding the description given by MDN. Let me break it down.
The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation
This means it will tell the browser that you wish to preform an animation that will require repainting. But to do that, we are going to need to run some code.
and requests that the browser call a specified function to update an animation before the next repaint.
This means that just before the next repaint, which the animation would require, call my callback function.
requestAnimationFrame
is not a paint event callback, but a means of firing a callback before the next paint which the browsers must now preform.
The following blog post really helped me understand how the whole thing works.
From it:
Essentially, the whole event loop function can be illustrated with this code:
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()
}
}
And depict like so:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With