JavaScript

Use of requestAnimationFrame for animation

It's hard to see what requestAnimaionFrame() does without reading about it. The traditional way of doing animation is to generate one frame then then run setTimeout at a specific time interval to make the animation as smooth as possible. For example if you want 60 frame per second you would run it every 16.67ms.

// Fade out
function fadeOut(element) {
    var opacity = 1,
    fps = 1000/60;  // 16.67 ms
    function decrease () {
        opacity -= 0.05;
        if (opacity <= 0){
            // complete
            element.style.opacity = 0;
            return true;
        }
        element.style.opacity = opacity;
        setTimeout(decrease,fps);
    }
    decrease();
}

That's a simple fade out animation. It should run fast. But if some reason your decrease() function takes longer then 16ms to run, you will have a choppy animation. And if you happen to switch tabs, the animation would still be running in the background (draining your battery).

Using requestAnimationFrame lets the browser handle when is the best time to run the code. It will try to run it at 60 frame per second. It is optimized to run as smooth as possible. Making the switch is as simple as replacing your setTimeout function with requestAnimationFrame.

function fadeOut(element) {
    var opacity = 1;
    function decrease () {
        opacity -= 0.05;
        if (opacity <= 0){
            // complete
            element.style.opacity = 0;
            return true;
        }
        element.style.opacity = opacity;
        requestAnimationFrame(decrease);
    }
    decrease();
}

Now the browser will take care of running your animation at the best possible time. There is a catch however. requestAnimationFrame is only available in newer browsers. There is always someone that will come using an old browser and it will fail. What we can do is write a fall back to use setTimeout if the feature is not available.

if (!window.requestAnimationFrame) {
    window. requestAnimationFrame = function (fn) {
        var timer = 16.66; // 60 fps
        setTimeout(fn,timer);
    }
}

That's all it takes. If the user's browser supports it, they get a better experience, otherwise, well we give them what their browser support.


Comments(4)

Jack :

awesome post. Really logical and cool to find a simple method to not use jQuery! Thank you

Devin :

You referenced requestTimeAnimation in your 4th paragraph and meant requestAnimationFrame. Also spelled requestAnimationFrame()

wrong in the first paragraph. Not a stickler, just happened to catch those things. Thanks for the article.

Ibrahim :

Thank you Devin, I wrote requestAnimationFrame and setTimeout so much that I ended up mixing them :D.

Thank you for finding the error.

Anthony Laurence Yap :

This is a cool tip. It can be applied on so many things, not only for fade in and fade out effects. Mainly, this is useful for all sorts of animation effects. Thanks Man.

Let's hear your thoughts

For my eyes only