Some Gloss: Dojo Animations

November 3rd, 2009 - by torrey
This entry is part 6 of 9 in the series Dojo Quick Start Guide

Dojo has a powerful animation system with several pre-made animations for a lot of common use cases. Adding some visual flair to you projects has never been easier, and typically makes the users experience a lot more interesting.

All animations use a single “magic object” as it’s only parameter. The most important being the node: attribute, the domNode on which to apply our animation. Some parameters are optional, and some are for advanced usage. A common setup would look something similar to:

dojo.addOnLoad(function(){
     var animArgs = {
          node: "testHeading",
          duration: 1000, // ms to run animation
          delay: 250 // ms to stall before playing
     };
     dojo.fadeOut(animArgs).play();
});

Base Animations:

Animations included in base dojo.js are: fadeIn, fadeOut, and animateProperty. dojo.animateProperty is very powerful, and is the foundation for most advanced animations, and other animations in Dojo Core.

dojo.addOnLoad(function(){
     dojo.style("testHeading","opacity","0"); // hide it
     var anim1 = dojo.fadeOut({ node: "testHeading", duration:700 });
     var anim2 = dojo.animateProperty({
       node: "testHeading", delay: 1000,
       properties:{
          // fade back in and make text bigger
          opacity: { end: 1 }, fontSize: { end:19, unit:"pt"}
       }
     });
     anim1.play();
     anim2.play();     
});

As seen, dojo.animateProperty will fade the element back in via it’s opacity property, and simultaneously make the text larger. You can animate most any CSS property this way.

In JavaScript, when modifying multi-word properties such as font-size and border-top, you must use a mixed cased version, as hypens are illegal as keys. Use fontSize and lineHeight, instead of font-size or line-height for example.

Additional FX

A lot can be done visually with the base animations, animateProperty especially. To keep the size of the base dojo.js down, all the additional animations and tools have been packaged into a single module: dojo.fx to be optionally called in via dojo.require. Adding the module to your code provides several additional animation methods: dojo.fx.combine, dojo.fx.chain, dojo.fx.wipeIn, dojo.fx.wipeOut and dojo.fx.slideTo.

dojo.require("dojo.fx");
dojo.addOnLoad(function(){
     // slide the node to 75,75
     dojo.fx.slideTo({
       node:"testHeading",
       top:75, left:75
     }).play(); // and play it
});

dojo.fx.chain and dojo.fx.combine are very useful, too. They run animations in parallel or in sequence, returning a single instance of dojo._Animation to use:

dojo.require("dojo.fx");
     dojo.addOnLoad(function(){
       var anim = dojo.fadeOut({ node: "testHeading" });
       var anim2 = dojo.fadeIn({ node: "testHeading" });
       dojo.fx.chain([anim,anim2]).play();
});

Combining an animation to fade in and out wouldn’t make sense, so lets fade it out and slide the node simultaneously using dojo.fx.combine:

dojo.require("dojo.fx");
     dojo.addOnLoad(function(){
       var anim = dojo.fadeOut({ node: "testHeading" });
       var anim2 = dojo.fx.slideTo({ node: "testHeading", top:75, left:75 });
       var result = dojo.fx.combine([anim,anim2]);
       result.play();
});

Animation Events

Each dojo._Animation has a series of “events” to tie into for more advanced usage. Going back to the one-stop-event-shop dojo.connect, we can connect to specific actions of the animation, and do other things. The most common are onEnd and beforeBegin:

dojo.addOnLoad(function(){
     var anim = dojo.fadeOut({ node: "testHeading" });
     dojo.connect(anim,"onEnd",function(){
       console.log(" the animation is done ");
     });
     dojo.connect(anim,"beforeBegin",function(){
       console.log(" the animation is about to start ");
     });
     anim.play();
});

These events are especially helpful when you want to do things like change some content out while a node is hidden and then fade it back in:

dojo.addOnLoad(function(){
     var anim = dojo.fadeOut({ node: "testHeading" });
     dojo.connect(anim,"onEnd",function(){
        dojo.byId("testHeading").innerHTML = "replaced after fade!";
        dojo.fadeIn({ node:"testHeading" }).play();
     });
     anim.play();
});

Conveniently, you can pass the event functions as properties to the animation. Using dojo.connect to setup the functions gives us a lot more power, and are typically safer for advanced uses, but sometimes it’s easier to wrap it all in:

dojo.addOnLoad(function(){
     var anim = dojo.fadeOut({
        node: "testHeading",
        onEnd: function(){
           dojo.byId("testHeading").innerHTML = "replaced … ";
           dojo.fadeIn({ node: "testHeading" }).play();
        }
     }).play();
});

The full explanation of events is available at the dojo._Animation API pages.

animateProperty

Probably the most powerful of the base animations, dojo.animateProperty allows us to easily animate multiple css properties simultaneously.

Since animateProperty is a dojo._Animation, it uses the same arguments as other animations. With an additional object, properties we can define any style property of a node. From start to end, and optionally using a unit attribute.

Manipulating our header element to use a new font color, size, and overall opacity is as easy as:

dojo.addOnLoad(function(){
     var anim = dojo.animateProperty({
        node:"testHeading",
        duration:700,
        properties: {
          // javascript css names are camelCase
          // (not hyphenated)
          fontSize: { start:12, end:22, unit:"pt" },
          opacity: { start:1, end:0.5 },
          color: { start: "#000", end:"#FFE" }
        },
        delay:100 // Note! trailing commas break IE.
     });
     anim.play();
});

dojo.query Animations

Dojo provides another convenient module: dojo.NodeList-fx, which adds additional methods to dojo.query for the available dojox.fx animations. To enable these methods, simply add in the required module:

dojo.require("dojo.NodeList-fx");
     dojo.addOnLoad(function(){
       dojo.query("#testHeading").fadeOut().play();
});

The above gives us the same effect as calling dojo.fadeOut directly, but dojo.query here makes an animation for each of of the NodeList elements, and combines them into a single dojo._Animation. This can be useful when you have groups of like nodes you want to easily affect (in this case, all the nodes with class=”fadeNode”):

dojo.require("dojo.NodeList-fx");
var fadeThem = function(){
     dojo.query(".fadeNode").fadeOut().play();
}
dojo.addOnLoad(function(){
     dojo.connect(dojo.byId("testHeading"),"onclick","fadeThem");
});
Unlike other dojo.query() chains, the NodeList-fx methods return an instance of dojo._Animation, preventing further chaining.
Bookmark and Share

Leave a Reply