You need to know about requestAnimationFrame

With the development of the front end, CSS has been able to achieve a lot of animation effects, but there are still animation tasks that CSS cannot accomplish (such as page scrolling), the common solution is to use setInterval in JS to set timers to achieve animation effects, such as the following basic animation loop.

(function() {
  function updateAnimations() {
    doAnimation1();
    doAnimation2();
  }
  setInterval(updateAnimations, 100); }) ();Copy the code

What this code does is perform a function every 100 milliseconds to animate, but is it really reliable to use timers? The answer, of course, is no

Since JavaScript is single-threaded, the timer is implemented after the current task queue completes. If the execution time of the current task queue is longer than the delay time set by the timer, then the timer is not reliable, as shown below:

let startTime = new Date().getTime();
setTimeout((a)= >{
  let endTime = new Date().getTime();
  console.log(endTime - startTime);
},50)

for(let i=0; i<20000; i++) {console.log(1);
}
Copy the code

The output is as follows

As you can see, if you set the execution time to 50 milliseconds, the actual execution delay is much higher than this, which will result in the animation not being as desired.

Animations are drawn frame-by-frame by the browser at a certain frequency. The advantage of animations implemented by CSS is that the browser knows the start of animation and the interval of each frame cycle, and can refresh the UI at the appropriate time, giving the user a smooth experience. JavaScript animations implemented by setInterval or setTimeout are not as reliable, because the browser cannot guarantee the interval between frames of rendering. In general, an average refresh rate of 60 frames per second is a smooth experience. That means rendering a new frame every 1000/60 milliseconds, but from the example above, timers alone can’t guarantee this. For this reason, requestAnimationFrame was created to allow the browser to perform animations smoothly. You can think of it as an API for animation, where you can tell the browser that certain JavaScript code is going to animate, and when the browser gets notified, it optimizes the code as it runs, achieving smooth results without the developer having to worry about how often to refresh.

The usage method is as follows:

function animationWidth() {
  var div = document.getElementById('box');
  div.style.width = parseInt(div.style.width) + 1 + 'px';

  if(parseInt(div.style.width) < 200) {
    requestAnimationFrame(animationWidth)
  }
}
requestAnimationFrame(animationWidth);
Copy the code

The effect is as follows (GIF recorded dot card… Actual effect please refer to the example) :

As you can see, requestAnimationFrame takes an animation-executing function as a parameter. This function performs a rendering of just one frame of animation and determines whether the animation is finished based on the condition. If the animation is not finished, requestAnimationFrame is called and passes itself as a parameter. From the example, the result is a smooth and smooth animation, which cleverly avoids the problem of the time interval between each frame of animation rendering.

See Caniuse for requestAnimationFrame compatibility

In advanced browsers, the developer does not have to worry about the time interval for each frame to render. In older browsers, setTimeout is used to simulate requestAnimationFrame, and the implementation of requestAnimationFrame depends on the browser. The name of the API is also slightly different. A mock requestAnimationFrame for older browsers is written as follows (from Zhang Xinxu’s blog) :

(function() {
    var lastTime = 0;
    var vendors = ['webkit'.'moz'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] | |// The name of this cancel method in Webkit has changed
                                      window[vendors[x] + 'CancelRequestAnimationFrame'];
    }

    if (!window.requestAnimationFrame) {
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0.16.7 - (currTime - lastTime));
            var id = window.setTimeout(function() {
                callback(currTime + timeToCall);
            }, timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
    }
    if (!window.cancelAnimationFrame) {
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
    }
}());
Copy the code

Without explaining what this means, if you encounter animation requirements from older browsers, you just need to throw in this code and define a requestAnimationFrame method with a lower version (save your life and stay away from older browsers).

Finally, I will post an example of frame animation in the department’s work

Reference:

  1. JavaScript advanced programming
  2. CSS3 animation is so strong, requestAnimationFrame is still used?

If there are mistakes, welcome to correct!

  • My lot