Castle and Riders

Animation Chains with jQuery

Using the animate() function built into the core jQuery library, you can generate complex, multi-step movement or visual effects using any element on your Web page. No Flash or Silverlight is needed, just the CSS and JavaScript capabilities built into your browser. The secret to complex animations is jQuery’s ability to “chain” multiple functions together to apply actions sequentially. Here’s a sample:

AvatarGauth

In the animation above, notice how the missile first travels from the avatar to the monster, then turns into a starburst that fades out and disappears. This effect is actually three separate animate() functions chained together. Let’s break it apart to see how it works.

First, Some Setup

I have placed three images on the page: an avatar graphic, a monster graphic, and a missile graphic which is initially hidden (display: none). I actually put all three of them inside a div to keep them together, but this is not strictly necessary — they can be anywhere on the page. I also give each <img> tag a unique id I can reference later.

<div style="width:50%; height:32px; margin-left:25%">
    <img src="avatar.gif" alt="Avatar" width="32" height="32" id="avatar" style="float:left" />
    <img src="missile.gif" alt="Missile" width="32" height="32" id="missile" style="position:absolute; z-index: 1; display:none"/>
    <img src="gauth.gif" alt="Gauth" width="32" height="32" style="float:right; z-index:0" id="gauth"/>
</div>

Bring On jQuery

Now I pull in jQuery from Google’s AJAX Libraries API page. Google has made many of the most popular JavaScript libraries freely available for developers via hosted URLs so you don’t even need to download and install them on your server. That’s just awesome.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>

I have chosen the minified version of jQuery 1.2.6, but you can get the latest version automatically if you prefer.

Where’s the Missile?

For convenience I assign the missile image (selected with that unique id I set above) to a $missile variable. Now I need to figure out where to send the missile. JQuery provides a method to find the position of any element named, oddly enough, position(). I select the gauth and assign the position object to a $end variable. The position object contains two properties: top and left.

<script type="text/javascript">
    $missile = $("#missile");
    $end = $("#gauth").position();
    $missile.show();

Just before firing off the animation, I display the image using the show() function.

Let’s Animate!

The general form of a chained animation is a series of animate() calls for each step of the animation:

jQueryObject.animate().animate().animate().etc.

For each animate() step, any number of style properties can be set as endpoints for that stage of the animation. When you chain the animate() functions together, you create more complex animations or effects. Here are all three parts of the animation chain:

    $missile.animate(
        {top: $end.top + "px", left: $end.left + "px"},
        900,
        "linear",
        function() { $missile.attr({ src: "hit.gif" }); }
    ).animate(
        {opacity: 0.5},
        600,
        "swing"
    ).animate(
        {top: "hide"},
        1
    );

In this example, the three animate() functions correspond to these three steps in the animation:

  1. Move the missile from avatar to monster
  2. Fade out the missile
  3. Hide the missile

In the first step, the graphic moves to new top and left coordinates in 900 milliseconds at a constant “linear” velocity. In the second step, the graphic becomes 50% transparent in 600 milliseconds at a non-linear “swing” rate. The final step is to make the graphic disappear instantly (actually, in one millisecond) by setting a CSS property to a value of “hide.”

Something is Missing

A missing step is swapping the missile image with a starburst image to represent a “hit.” JQuery’s animate() function only supports changing style properties, and even then it only works with style properties using numeric values. So, for example, I can’t change a background graphic or set a src attribute on an <img> tag. However, animate() supports a handy callback function that virtually eliminates limitations like this.

Here’s how it works: At any step in the animate() chain, pass a function parameter as a callback. When that step of the animation is done, it will halt the chain, call your function, and then continue with the next step in the chain. This means you can insert callbacks to do virtually anything, even operations completely outside the scope of the animation.

I use a callback as the fourth parameter in the first animate() function, which looks like this:

function() { $missile.attr({ src: "hit.gif" }); }

In this callback I swap the missile graphic with a hit.gif starburst graphic. This occurs before the second step of the animation begins.

Putting It All Together

Here is the complete code to create this animation:

<div style="width:50%; height:32px; margin-left:25%">
    <img src="avatar.gif" alt="Avatar" width="32" height="32" id="avatar" style="float:left" />
    <img src="missile.gif" alt="Missile" width="32" height="32" id="missile" style="position:absolute; z-index: 1; display:none"/>
    <img src="gauth.gif" alt="Gauth" width="32" height="32" style="float:right; z-index:0" id="gauth"/>
</div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript">
    $missile = $("#missile");
    $end = $("#gauth").position();
    $missile.show();
    $missile.animate(
        {top: $end.top + "px", left: $end.left + "px"},
        900,
        "linear",
        function() { $missile.attr({ src: "hit.gif" }); }
    ).animate(
        {opacity: 0.5},
        600,
        "swing"
    ).animate(
        {top: "hide"},
        1
    );
</script>


Posted on November 9th, 2008 in the JavaScript category | Permalink
You can follow any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.

Leave a Reply

You must be logged in to post a comment.