public
Last active — forked from paulirish/rAF.js

requestAnimationFrame polyfill

  • Download Gist
requestanimationframe.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/**
* requestAnimationFrame polyfill by Erik Möller & Paul Irish et. al.
* https://gist.github.com/1866474
*
* http://paulirish.com/2011/requestanimationframe-for-smart-animating/
* http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
**/
 
/*jshint asi: false, browser: true, curly: true, eqeqeq: true, forin: false, newcap: true, noempty: true, strict: true, undef: true */
 
(function( window ) {
 
'use strict';
 
var lastTime = 0;
var prefixes = 'webkit moz ms o'.split(' ');
// get unprefixed rAF and cAF, if present
var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame;
// loop through vendor prefixes and get prefixed rAF and cAF
var prefix;
for( var i = 0; i < prefixes.length; i++ ) {
if ( requestAnimationFrame && cancelAnimationFrame ) {
break;
}
prefix = prefixes[i];
requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ];
cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] ||
window[ prefix + 'CancelRequestAnimationFrame' ];
}
 
// fallback to setTimeout and clearTimeout if either request/cancel is not supported
if ( !requestAnimationFrame || !cancelAnimationFrame ) {
requestAnimationFrame = function( callback, element ) {
var currTime = new Date().getTime();
var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
var id = window.setTimeout( function() {
callback( currTime + timeToCall );
}, timeToCall );
lastTime = currTime + timeToCall;
return id;
};
 
cancelAnimationFrame = function( id ) {
window.clearTimeout( id );
};
}
 
// put in global namespace
window.requestAnimationFrame = requestAnimationFrame;
window.cancelAnimationFrame = cancelAnimationFrame;
 
})( window );

This prevents use of vendorRequestionAnimationFrame unless the equivalent is supported for cancelAnimationFrame.

I ran into an issue with Firefox 10, where mozRequestAnimationFrame is supported, but not an equivalent for cancelAnimationFrame. So I was able to start an animation, but not properly stop it.

Also, has some personal whitespace and code style tweaks.

I think it would be a lot better to emulate cancelAF() than to completely abort if it's not available. To emulate on browsers without a cancel, wrap pending callbacks along with their IDs and have cancel() set a bit that marks that ID as cancelled. That's in fact exactly we do in the browser.

@charliewalnut Agreed that it's a shame to throw out requestAF with cancelAF. Can you provide a fork with this implementation?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.