Created
July 29, 2011 17:34
-
-
Save louisremi/1114293 to your computer and use it in GitHub Desktop.
Animation loop with requestAnimationFrame
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function animLoop( render, element ) { | |
var running, lastFrame = +new Date; | |
function loop( now ) { | |
// stop the loop if render returned false | |
if ( running !== false ) { | |
requestAnimationFrame( loop, element ); | |
var deltaT = now - lastFrame; | |
// do not render frame when deltaT is too high | |
if ( deltaT < 160 ) { | |
running = render( deltaT ); | |
} | |
lastFrame = now; | |
} | |
} | |
loop( lastFrame ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function animLoop( render, element ) { | |
var running, lastFrame = +new Date; | |
function loop( now ) { | |
// stop the loop if render returned false | |
if ( running !== false ) { | |
requestAnimationFrame( loop, element ); | |
running = render( now - lastFrame ); | |
lastFrame = now; | |
} | |
} | |
loop( lastFrame ); | |
} | |
// Usage | |
animLoop(function( deltaT ) { | |
elem.style.left = ( left += 10 * deltaT / 16 ) + "px"; | |
if ( left > 400 ) { | |
return false; | |
} | |
// optional 2nd arg: elem containing the animation | |
}, animWrapper ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Cross browser, backward compatible solution | |
(function( window, Date ) { | |
// feature testing | |
var raf = window.mozRequestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.msRequestAnimationFrame || | |
window.oRequestAnimationFrame; | |
window.animLoop = function( render, element ) { | |
var running, lastFrame = +new Date; | |
function loop( now ) { | |
if ( running !== false ) { | |
raf ? | |
raf( loop, element ) : | |
// fallback to setTimeout | |
setTimeout( loop, 16 ); | |
// Make sure to use a valid time, since: | |
// - Chrome 10 doesn't return it at all | |
// - setTimeout returns the actual timeout | |
now = now && now > 1E4 ? now : +new Date; | |
var deltaT = now - lastFrame; | |
// do not render frame when deltaT is too high | |
if ( deltaT < 160 ) { | |
running = render( deltaT, now ); | |
} | |
lastFrame = now; | |
} | |
} | |
loop(); | |
}; | |
})( window, Date ); | |
// Usage | |
animLoop(function( deltaT, now ) { | |
// rendering code goes here | |
// return false; will stop the loop | |
... | |
// optional 2nd arg: elem containing the animation | |
}, animWrapper ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var elem = document.getElementById("animatedElem"), | |
left = 0, | |
lastFrame = +new Date, | |
timer; | |
// Move the element on the right at ~600px/s | |
timer = setInterval(function() { | |
var now = +new Date, | |
deltaT = now - lastFrame; | |
elem.style.left = ( left += 10 * deltaT / 16 ) + "px"; | |
lastFrame = now; | |
// clear the timer at 400px to stop the animation | |
if ( left > 400 ) { | |
clearInterval( timer ); | |
} | |
}, 16); |
Thanks for the code snippets.
I think there's a bug in animLoopX.js.
if deltaT is too big, lastFrame never gets updated, so the loop never calls render anymore!
You're absolutely right, I updated it.
Thanks
Would this do the same thing? It's simpler:
// Periodically call render(timeInterval) via requestAnimationFrame on
// element until it returns false. (But call render only when the
// interval is < 160ms; otherwise wait and try again, hoping for a
// reasonable interval.)
function animLoop(render, element) {
var then = Date.now();
function loop(now) {
var interval = now - then;
if (160 <= interval || render(interval) !== false)
requestAnimationFrame(loop, element);
then = now;
}
loop(then);
}
(Do any browsers or specifications use this element parameter?)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I make it a principle of not including un-prefixed APIs, as long as it isn't available in any browser.
requestAnimationFrame probably won't change much, but there's no point in adding prefixes if shims are written with assumptions that the final version of the API will behave exactly like the drafts.