Gecko 2.0 adds a new method for performing JavaScript controlled animations that synchronize not only with one another, but also with CSS transitions and SMIL animations being performed within the same window.

Usage outline

In order to time your animation, the first thing you need to know is the time base; that is, the time at which your animation sequence started. You can determine this value by looking at window.mozAnimationStartTime. This new property indicates the time, in milliseconds since epoch, at which all animations started in the specified window during the current refresh interval should be considered to have started running.

With that value in hand, you can then schedule all your subsequent animation frames. Whenever you're ready to refresh your animation, you call the window.requestAnimationFrame() method. Once you've called this, the MozBeforePaint event will be fired one time, when it's time for animations to be updated for the window's next animation frame.  The timeStamp property of this event will be set to the time when the animation frame is sampled; this is relevant when trying to synchronize mozRequestAnimationFrame animations with SMIL animations or CSS transitions.

This allows multiple animations to remain in sync with one another within the context of a given window.

Frame rate control

MozBeforePaint won't fire more than a fixed number of times per second, e.g. 50 or 60. This is intentional, because modern operating systems and hardware won't let the browser display more frames than that anyway. Limiting the frame rate avoids wasting work, thereby saving CPU usage and power and improving overall system performance.

Example

This example performs a simple animation, moving a box a short distance after a short period of time.

<!DOCTYPE HTML>
<html>
<body>
<div id="d" style="width:100px; height:100px; background:lime; position:relative;"></div>
<script>
var d = document.getElementById("d");
var start = window.mozAnimationStartTime;
function step(event) {
  var progress = event.timeStamp - start;
  d.style.left = Math.min(progress/10, 200) + "px";
  if (progress < 2000) {
    window.mozRequestAnimationFrame();
  } else {
    window.removeEventListener("MozBeforePaint", step, false);
  }
}
window.addEventListener("MozBeforePaint", step, false);
window.mozRequestAnimationFrame();
</script>
</body>
</html>

As you can see, each time the MozBeforePaint event fires, our step() method is called. This computes the current position for the animating box and updates the box's position on screen, and, if the animation sequence is not yet complete, calls window.requestAnimationFrame() to schedule the next animation frame to be drawn. When the animation sequence completes, removes the event listener.

You may take a look at this example live if you like.

See also