Archive for category Animation

Animating With Firefox’s mozRequestAnimationFrame

Firefox 4 is going to be a very exciting release. Robert O'Callahan details one of the new features, which should help animation, called mozRequestAnimationFrame. First the motivation:

In Firefox 4 we've added support for two major standards for declarative animation --- SVG Animation (aka SMIL) and CSS Transitions. However, I also feel strongly that the Web needs better support for JS-based animations. No matter how rich we make declarative animations, sometimes you'll still need to write JS code to compute ("sample") the state of each animation frame. Furthermore there's a lot of JS animation code already on the Web, and it would be nice to improve its performance and smoothness without requiring authors to rewrite it into a declarative form.

setTimeout and setInterval can only go so far; as Robert describes, we sometimes need something between purely JavaScript-driven animation using setTimeout and having to go full declarative using CSS3 or SMIL. mozRequestAnimationFrame is one potential way to get better synchronization and performance from JavaScript based animation.

Some sample code from Robert using it:

JAVASCRIPT:
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();
 

It's not very different from the usual setTimeout/Date.now() implementation. We use window.mozAnimationStartTime and event.timeStamp instead of calling Date.now(). We call window.mozRequestAnimationFrame() instead of setTimeout().

Note that you will generally get about 50 frames per second using mozRequestAnimationFrame. As Robert describes in another blog post, this is a feature not a bug:

On modern systems an application usually cannot get more than 50-60 frames per second onto the screen...So even if an application updates its window 100 times a second, the user won't be able to see more than about half of those updates...firing a MozBeforePaint event more than about 50 times a second is going to achieve nothing other than wasting CPU (i.e., power). So we don't. Apart from saving power, reducing animation CPU usage helps overall performance because we can use the free time to perform garbage collection or other house-cleaning tasks, reducing the incidence or length of frame skips.

I hope that other browsers pick up this feature.

Animated CSS3 cube using 3D transforms

I've been doing alot of experimenting with HTML5/CSS3 on the iPhone doing animation, and I've been surprised with the low frame rate of animating through Canvas or SVG. If you are trying to do animation, especially 3D, on the iPhone it seems like the name of the game is to it through the GPU, and the only way to do that these days on iOS is CSS3 Animations/Transitions/3D.

These experiments caused me to stumble on Paul Hayes interesting work simulating a 3D animated cube using CSS3, hence they happen on the GPU on the iPhone/iPad and are quite fast:

A 3D cube can be created solely in CSS, with all six faces. Using JavaScript to detect key presses and update inline styles this cube can be intuitively navigated.

Demo (Webkit only)

Paul achieves this by having each face of the cube be a unique DIV, each with a 'face' class and inside of a larger 'cube' class all wrapped by an 'experiment' class:

HTML:
<div id="experiment">
        <div id="cube">
                <div class="face one">
                        One face
                </div>
                <div class="face two">
                        Up, down, left, right
                </div>
                <div class="face three">
                        Lorem ipsum.
                </div>
                <div class="face four">
                        New forms of navigation are fun.
                </div>
                <div class="face five">
                        Rotating 3D cube
                </div>
                <div class="face six">
                        More content
                </div>
        </div>
</div>
 

The outer wrapper is the camera and allows you to apply perspective and where you want the perspective origin to be:

CSS:
#experiment {
    -webkit-perspective: 800;
    -webkit-perspective-origin: 50% 200px;
}
 

The #cube itself is given a size, CSS transition properties so things will animate nicely, and an instruction to preserve 3D children and not 'flatten' them:

CSS:
#cube {
    position: relative;
    margin: 0 auto;
    height: 400px;
    width: 400px;
    -webkit-transition: -webkit-transform 2s linear;
    -webkit-transform-style: preserve-3d;
}
 

Each of the faces is given some common styling:

CSS:
.face {
    position: absolute;
    height: 360px;
    width: 360px;
    padding: 20px;
    background-color: rgba(50, 50, 50, 0.7);
}
 

The individual face DIVs are then rotated and translated in 3D space into their correct positions:

CSS:
#cube .one {
      -webkit-transform: rotateX(90deg) translateZ(200px);
    }

    #cube .two {
      -webkit-transform: translateZ(200px);
    }

    #cube .three {
      -webkit-transform: rotateY(90deg) translateZ(200px);
    }

    #cube .four {
      -webkit-transform: rotateY(180deg) translateZ(200px);
    }

    #cube .five {
      -webkit-transform: rotateY(-90deg) translateZ(200px);
    }

    #cube .six {
      -webkit-transform: rotateX(-90deg) translateZ(200px) rotate(180deg);
    }
 

Read more in Paul's post.