What the requestAnimationFrame API Should Have Looked Like

Chrome, Firefox and IE10 now support requestAnimationFrame – a noble idea, with a totally backwards API.

Imagine you have this JavaScript animation that you want to constantly update. An animation that constantly updates, needs to be updated more than once, i.e. constantly. After all it's an animation. So why on earth do I have an API to request one update at a time?

Mozilla's documentation even warns developers that the API might not work as expected:

Note: Your callback routine must itself call requestAnimationFrame() unless you want the animation to stop.

Ah, yes.

Car analogy time: I have this very nice car that makes a beeping noise whenever I open the door with the ignition off and the headlights still on. You know, to warn me that my headlights might run the battery dry in my absence. "Thank you car, that's very kind of you. But let me ask you something: why didn't you just turn the headlights off yourself instead of notifying me?"

The requestAnimationFrame API is modeled after setTimeout when it should've been modeled after setInterval instead.

Here's my proposal:

var animationId = setAnimation ( callback , element ); clearAnimation ( animationId );

And the code to make this happen:

( function ( w ) { "use strict" ; var vendors = [ 'ms' , 'moz' , 'webkit' , 'o' ]; for ( var i = 0 ; i < vendors . length && ! w . requestAnimationFrame ; i ++ ) { w . requestAnimationFrame = w [ vendors [ i ]+ 'RequestAnimationFrame' ]; } if ( w . requestAnimationFrame ) { var next = 1 , anims = {}; w . setAnimation = function ( callback , element ) { var current = next ++; anims [ current ] = true ; var animate = function () { if ( ! anims [ current ] ) { return ; } w . requestAnimationFrame ( animate , element ); callback (); }; w . requestAnimationFrame ( animate , element ); return current ; }; w . clearAnimation = function ( id ) { delete anims [ id ]; }; } else { w . setAnimation = function ( callback , element ) { return w . setInterval ( callback , 1000 / 60 ); } w . clearAnimation = w . clearInterval ; } }( window ));

Gist on Github