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. requestTimeAnimation 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

Jack :

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

Let's hear your thoughts

For my eyes only