SetTimeout is different from requestAnimationFrame

This is the 26th day of my participation in the More Text Challenge. For more details, see more text Challenge

When you mention setTimeout and requestAnimationFrame, the first thing that comes to mind is that there are two apis related to animation. Let’s talk about what animation is. Animation is actually an illusion, a discontinuous motion presented to us in the form of frames. In the 20th century, people usually watched films that were actually recorded and projected on film. It’s a visual illusion of motion at a rate of at least 24 frames per second. The standard NTSC broadcast frame rate is 23.975FPS, compared with 25FPS for PAL. FPS can be thought of as “refresh rate (in Hz)”, as in “FPS value” in games. We all pay attention to the “refresh rate” when installing graphics cards and monitors. We usually set the default refresh rate above 75Hz (75 frames per second). For example, a 75Hz refresh rate means that the screen is only scanned 75 times per second, or 75 frames per second. And when the refresh rate is too low, our naked eyes can feel the screen flicker, inconsistent, the image display effect and visual perception has a bad impact. As a result, at least 24FPS is needed to animate, but the animation is not smooth and smooth. Smooth animation requires a wireless frame rate, but the human brain can’t detect that frame rate, so 60FPS is pretty good. Most modern devices, such as computers and smartphones, refresh their screens at 90FPS, while a few gaming systems support 120FPS. So what is a frame? There is no absolute definition of this and it depends on the context in which it is used. For example, each frame of a movie film is determined by the FPS being recorded. When recording a video, set the camera to 30FPS, and the resulting 30 individual images must be played at 30FPS for 1 second. However, when discussing the Web, the definition of a frame changes again. For Web animations, we can move 1px or more across the device screen. The fewer pixels there are to move an element (DOM element), the smoother and smoother the animation. A frame is a snapshot of the DOM element’s position on the screen in real time. In 1s, if an element moves 60px at 1px a time, the FPS value is 60. This is equivalent to moving 120px at 2px a time. Although the speed of movement is greater, the animation will not be smoother because the corresponding elements will also move farther. So, how do you animate DOM elements using JavaScript? You can use setTimeout or setInterval in JavaScript.

  • The setTimeout function executes the callback function after n milliseconds. The callback function can be called recursively to implement the animation.
  • SetInterval calls the callback function at an interval of n milliseconds.

To achieve 60FPS, we need to move an element 60 times /s, which means that the element has to move about 16.7ms (1000ms/60frames). The figures above are based on our theoretical calculations. When we execute setTimeout(function () {}, 1000/60), does it really execute after 1000/60 milliseconds? Those of you who know the setTimeout mechanism will know that it doesn’t have to be executed after 1000/60 milliseconds, it could be longer. So why?

Event queues in JavaScript

As we all know, JavaScript engines are single-threaded, executing only one task at a given time and blocking the execution of other tasks, that is, these tasks are serial. In this case, the user has to wait for a time-consuming operation to complete before moving on to the next operation, which is obviously unacceptable, but in real development we can use asynchronous code to solve this problem. When asynchronous methods, such as setTimeout() here, or ajax requests or DOM events are executed, they are managed by other modules in the browser kernel. When the asynchronous method satisfies the triggering condition, the module will push the method into a task queue. When the main thread code is in idle state after execution, it will check the task queue, push the first task in the queue for execution, and continue to check the task queue after completion, so on. The precondition is that the main thread is idle, which is the model of the event loop. Js engine single thread execution, it is based on the event driven language. Its order of execution follows a mechanism called event queuing. Browsers have a variety of threads, such as event triggers, network requests, timers, and so on. When the JS engine processes code related to other threads, it will be distributed to other threads. After they finish processing, when the JS engine needs to calculate, it will add a task to the event queue. During this process, JS does not block the code until the other threads finish executing, and after the other threads finish executing, they add event tasks to tell the JS engine to perform related operations. This is the asynchronous programming model of JS. Within the specified time, the task is put into the event queue, waiting for the JS engine to idle after the execution. This explains why it is supposed to execute after 16 seconds, but probably at 18 seconds, because the JS engine is processing something else. SetTimeout /setInterval is not just an unpunctuality problem. There are other questions, summarized as follows:

  • The animator has no control over the number of frames;
  • When the label is hidden (not currently displayed), it consumes system resources unnecessarily.
  • SetInterval doesn’t care if the code it calls reports an error. Even if the calling code reports an error, it will continue to be called (which can be resolved with setTimeout).

Because of the above problems. The guys at Mozilla said, “Why don’t we make an API so that the animators don’t use the damn setInterval? Everyone (Chrome, IE, and the guy from Norway) agreed. So we have the requestAnimationFrame.

requestAnimationFrame

HTML5 new API, similar to the setTimeout timer. Window. The window object a method, requestAnimationFrame browser (so can only be used in the browser) API provided specifically for animation, DOM, Canvas, SVG animation, animation, animation WebGL has a uniform refresh mechanism and so on animation. Features:

  • Redraw a web page by frame. This method tells the browser that it wants to perform the animation and asks the browser to call the callback function to update the animation before the next redraw
  • The system decides when to execute the callback function, and the browser automatically optimizes the method call at run time

Monitors have a fixed refresh rate (60 hz or 75Hz), that is, a maximum of 60 or 75 redraws per second. The basic idea behind the requestAnimationFrame is to keep page redraws in sync with this refresh rate. For example, with a display screen refresh rate of 60Hz, using the requestAnimationFrame API, the callback function would be executed every 1000ms / 60 ≈ 16.7ms; If the display screen has a refresh rate of 75Hz, the callback function is executed every 1000ms / 75 ≈ 13.3ms. A callback function called through the requestAnimationFrame causes a page to be redrawn or reflow at the same interval as a display refresh. So requestAnimationFrame doesn’t need to pass the time interval like setTimeout, but instead the browser gets the display refresh rate from the system and uses it.

RequestAnimationFrame advantage

RequestAnimationFrame is similar to the setTimeout timer in terms of functionality and usage, so it has the advantage over the animation implemented by setTimeout.

  1. Improves performance and prevents frame drop

SetTimeout animates the image by setting an interval between changes. This method will appear in some low – end machine stutter, jitter phenomenon. There are generally two reasons for this phenomenon:

  1. The execution time of setTimeout is not determined.
  2. The refresh rate depends on the screen resolution and screen size, and the screen refresh rate may vary from device to device. SetTimeout can only set a fixed time interval, which may differ from the screen refresh interval

In either case, the setTimeout execution pace is inconsistent with the screen refresh pace, resulting in frame loss. The great advantage of using requestAnimationFrame for animation is that the callback function is executed only once per screen refresh interval, so no frames are lost and the animation is not stalled.

  1. Save resources, save power
  • When the page is hidden or minimized, the timer setTimeout is still performing the animation in the background. Refreshing the animation is completely meaningless. (In fact, FireFox/Chrome optimizes the timer: When the page is idle, if the interval is less than 1000ms, the timer is stopped, similar to the requestAnimationFrame behavior. If the interval is >=1000ms, the timer is still executed in the background.
  • With requestAnimationFrame, the screen refresh task for a page is paused when the page is inactive, and is also paused because the requestAnimationFrame keeps performing in sync with the screen refresh. When the page is activated, the animation continues where it left off, saving CPU overhead.