Animations with requestAnimationFrame

Recently I deceided to explore requestAnimationFrame as a way to peer behind the jQuery.animate veil. While you should absolutely use jQuery.animate (or similar) when working on a "real" project, the results were pretty interesting:

function animate(el, properties, duration, done) {
    function map(obj, transform){
        var result = {};
        Object.keys(obj).forEach(function (key) {
            result[key] = transform(key, obj[key]);
        });
        return result;
    }

    function accessor(property) {
        return {
            get: function (el) {
                var value = styles[property]
                if (value === 'auto') {
                    return 0;
                }

                return parseInt(value, 10);
            },
            set: function (el, value) {
                el.style[property] = value + "px";
            }
        };
    }

    var start,
        styles = getComputedStyle(el),
        startingValues = map(properties, function(key, value) {
            return accessor(key).get(el);
        });

    requestAnimationFrame(function step(timestamp) {
        done = done || function () {};
        start = start || timestamp;

        var elapsed = timestamp - start;

        Object.keys(properties).forEach(function (property) {
            var goal = properties[property],
                startingValue = startingValues[property],
                delta = goal - startingValue,
                progress = elapsed / duration,
                bound = (delta > 0 ? Math.min : Math.max),
                value = bound(delta * progress + startingValue, goal);

                accessor(property).set(el, value);
        });

        if (elapsed < duration) {
            requestAnimationFrame(step);
        } else {
            done();
        }
    });
}

Interestingly enough, the actual animation code is almost dwarfed by the code providing the API and fiddling with css properties to make sure they're in the right format.

Enough chit-chat, where's the bouncing ball?

I'm so glad you asked, I've even implemented the obligatory bouncing ball. Go take a look!