A dose of animation can give your app that extra bit of pizzazz that it sometimes needs to impress the customer/ladies/gentlemen/whatever-floats-your-boat, so I thought it might be a good idea to quickly showcase some of Dojo’s animation facilities.

If you’re just now tuning in, you can click on my mugshot or this link to get to the first two posts of the ongoing “Dojo Goodness” series that I’m writing to promote my upcoming book, Dojo: The Definitive Guide, which is available on Amazon as well as the O’Reilly catalog.

One of the first things you should know is that some of the most commonly used animation functions are packaged right into Base while others that offer more frill are available via Core’s fx module. A way to help keep track of where everything is at is to look at the namespace–everything in Base is located in the base level dojo namespace, while the Core add-ons are available via the dojo.fx namespace. For this episode, we’ll be using the fadeIn and fadeOut functions as well as the uber-flexible animateProperty function that are all included with Base. We’ll tap into dojo.fx to get chain and combine, which can be used to chain together and combine animations, respectively.

You can use Dojo’s official API to get the full scoop on any of the specific functions mentioned, but for brevity, we’ll stick to the most basic usage here. For the fading functions, that amounts to a couple of one-liners to fade in and fade out a node. As the upcoming snippet suggests, Dojo’s animation API generally returns an object that you have to manually start via its play() method. In addition to getting some other finely grained control, this makes it that much simpler to chain and combine animations (as you’ll see in a moment.) Finally, some code:


//fade some nodes!
dojo.fadeOut({node : 'someNodeId'}).play();
//then sometime later...
dojo.fadeIn({node : 'someNodeId'}).play();

The animateProperty function is pretty intuitive as well and is used to animate arbitrary CSS properties. For the upcoming example, we’ll be using it to animate the height and width of a square on the screen to create an implode and explode effect like so:


//create an implode animation
var implode = dojo.animateProperty({
   node : 'someNodeId',
   properties : {
       height : {end : 0},
       width  : {end : 0}
   }
}); 

//create an explode animation (assumes width and height are both 0 when it is run)
var explode = dojo.animateProperty({
   node : 'someNodeId',
   properties : {
       height : {end : 300}, //fill in whatever height/width you need...
       width  : {end : 300}
   }
});

But wait–that’s not all. Simple animations are cool and all, but we can also spice it up by chaining and combining them; as you’re about to see, it’s as easy as it should be. Here’s the chaining portion, which entails nothing more than passing in a series of animation objects to the dojo.fx.chain function:


//chain together two fade animations
dojo.fx.chain([
   dojo.fadeOut({node : 'someNodeId'}),
   dojo.fadeIn({node : 'someNodeId'})
]).play();

Combining works the very same way. If you wanted to combine a fadeOut and the custom implode function, you could do it like so:


//combine two animations
dojo.fx.combine([
   dojo.fadeOut({node : 'someNodeId'}),
   implode //the same one we created a few moments ago
]).play();

That’s it for the animation part of this episode, but to give you a way to manage all of this mayhem, let’s use some Button dijits, which make it dirt simple to execute JavaScript code. In this particular example, we’ll use dojo/method SCRIPT tags to intercept the Button dijit’s onClick extension point and kick of an animation all from markup! The general pattern works thusly:


<div dojoType="dijit.form.Button">Do Something!
    <script type="dojo/method" event="onClick" args="evt">
        //you can inspect the W3C standardized event object, evt, or do something else like...
        someAnimation.play();
        //other sweet JavaScript code goes here...
    </script>
</div>

So, without further ado, here’s the grand finale that puts all of this in perspective. This code creates a blue square in the center of your screen (relative to the viewport) and provides you with three buttons to control some animations. You should be able to copy and paste it directly into a local page and it should just work.


<html>
    <head>
        <title>Animation Station!</title>
        <style type="text/css">
            @import "http://o.aolcdn.com/dojo/1.0/dojo/resources/dojo.css";
            @import "http://o.aolcdn.com/dojo/1.0/dijit/themes/tundra/tundra.css";
        </style>

        <script
            type="text/javascript"
            src="http://o.aolcdn.com/dojo/1.0/dojo/dojo.xd.js"
            djConfig="parseOnLoad:true">
        </script>
        <script type="text/javascript">
            dojo.require("dojo.fx"); //for dojo.fx.chain and dojo.fx.combine
            dojo.require("dojo.parser");
            dojo.require("dijit.form.Button");

            dojo.addOnLoad(function() {

                //get the dimensions of the current viewport
                var viewport = dijit.getViewport();
                var viewport_height = viewport.h;
                var viewport_width = viewport.w;

                //center a square in the viewport
                var square_dimension = 300;
                var e = document.createElement("div");
                e.id = "square";
                dojo.style(e, "width", square_dimension);
                dojo.style(e, "height", square_dimension);
                dojo.style(e, "background", "blue");
                dojo.style(e, "position", "relative");
                dojo.style(e, "left", (viewport_width-square_dimension)/2);
                dojo.style(e, "top", (viewport_height-square_dimension)/2);
                dojo.body().appendChild(e);

                //chain together two fade animations
                fadeAnim = dojo.fx.chain([
                   dojo.fadeOut({node : 'square'}),
                   dojo.fadeIn({node : 'square'})
                ]);

                //set up an implode animation
                var implode = dojo.animateProperty({node : 'square',
                   properties : {
                       height : {end : 0},
                       width  : {end : 0}
                   }
                });
                //set up an explode animation
                var explode = dojo.animateProperty({node : 'square',
                   properties : {
                       height : {end : square_dimension},
                       width  : {end : square_dimension}
                   }
                });
                //chain together the implode/explode
                implExplAnim = dojo.fx.chain([implode,explode]);

                //combine the chained fades and the implode/explode
                fadeImplExplAnim = dojo.fx.combine([fadeAnim, implExplAnim]);

            });
        </script>
    </head>
    <body class="tundra">
        <div dojoType="dijit.form.Button">Fade In/Out
            <script type="dojo/method" event="onClick" args="evt">
                fadeAnim.play();
            </script>
        </div>

        <div dojoType="dijit.form.Button">Implode/Explode
            <script type="dojo/method" event="onClick" args="evt">
                implExplAnim.play();
            </script>
        </div>

        <div dojoType="dijit.form.Button">Both!
            <script type="dojo/method" event="onClick" args="evt">
                fadeImplExplAnim.play();
            </script>
        </div>
    </body>
</html>

As a final note, the soon to be released Dojo version 1.1 (currently in Beta 3) contains a couple of enhancements that further simplifies some of the version 1.0 syntax and saves you some typing. If you’re browsing the online API, don’t let those enhancements catch you off guard since the code on this page is using the latest version 1.0.x bug fix release.

Until Dojo: The Definitive Guide comes out, be sure to check back here each week for more Dojo goodness.