magazine resources subscribe about advertising

 

 

 








 CD Home < Web Techniques < 2001 < August  

Elastic Navigation with ActionScript

By Branden J. Hall

Web designers often gravitate toward Flash 5 because it lets you create navigational elements that are impossible to achieve with plain old HTML. Flash is well suited to this task, but most designers don't tap into my favorite part of Flash: ActionScript! I'm not talking about the simple stop-and-play actions that I'm sure you're familiar with; I'm talking about real math-based code. Yes, I said the M-word, and it gets worse. The math we'll be using is based on a subject most of us haven't thought about since high school—physics. Now, stop shaking in your boots so we can get started. It's not as scary as you think.

Motion Sense

First, let's learn how to make movie clips move with code. Start off by opening Flash and making a new, blank movie. Then, draw a circle on the stage and select it. We want to convert this shape into a movie clip symbol. Do so by either selecting Insert, Convert to Symbol or by pressing F8. Name the symbol MyCircle, and make it a movie clip. With our new movie clip selected, open the Actions panel. If the Actions panel isn't set to Expert mode, set it now (the setting is located in the arrow menu at the top right of the panel). In normal mode you have to pick your actions from the menu on the left and then fill in some blanks. In Expert mode you have to type everything yourself. Forcing yourself to use Expert mode will make you a better coder; you'll end up learning the language much faster. The code we'll attach to this movie clip is known as a clip event. This type of code block can only be attached to movie clip instances. The code looks like this:



onClipEvent(enterFrame){
  _x += 5;
}

You'll notice that the code is wrapped in an onClipEvent statement. Any code attached directly to a movie clip instance must be inside of an onClipEvent call. The enterFrame tells Flash we want this code to run every time Flash renders a frame. Because we didn't change the frame rate of our movie, this code will run at the default, 12 frames per second. The next line is a bit more confusing. We're setting a special variable that actually controls the x position of the movie clip. The += 5 tells Flash to simply add five to the current value of _x. If you test the movie now, you'll watch your movie clip move at a steady pace off the stage. This takes us to the next step: What if we don't want this movie clip to move at a steady pace toward a goal?

With Ease

We need to add a smidgen more code to change things, but the idea behind the code is pretty simple. Every frame halves the distance from our movie clip to the goal. While technically we'll never actually reach the goal, it's close enough for our purposes.

For this example, just jump back to the code you entered for the first example and change it to read:

onClipEvent(load){
   goal = 500;
}

onClipEvent(enterFrame){ _x += (goal - _x) / 2; }

The new clip event, load, runs only once—when the movie clip first loads. This event sets a variable goal for the clip's final position. Then, in the enterFrame clip event, we first find the difference between the current position of the movie clip and the goal (goal - _x). We halve this amount and add it to the current x position of the movie clip. If you test the movie, you'll notice that your movie clip slows down as it approaches the goal position. Now that we know how to move steadily or ease a clip into place, let's really get busy and make the movie clip bounce into place.

Flexibility

Before we start coding, we need to figure out how the bounce will work. Unlike the previous two examples, we need to track the actual speed of the movie clip. There are two parts to calculating speed. The first is taking the speed in the last frame and reducing it by a certain percentage—this simulates friction. The second part is to calculate the movie clip's distance from its goal, take a percentage of that amount, and add the value to the result of the first part. The actual equation looks something like this:


speed = speed * friction + (goal - _x) *           
        speedratio;

Both friction and speedratio exist as variables between 0 and 1 because they represent percentages. Friction is the percentage of the object's speed that remains from frame to frame, and speedratio controls how much the distance between the movie clip and the goal affects the object's speed. After you're done with this example, I recommend that you fiddle around with these values to observe the results. This exercise helps you understand how each component actually controls the clip's movement. Now let's look at our actual code (see Example 1).

You'll notice that we're just setting our variables in the load clip event. In the enterFrame clip event, we update the speed variable, and then increment the x position of the clip by the speed value. If you test the movie now, you'll see the clip bounce back and forth around its goal and eventually stop.

So—with just a little code—we can move, ease, and even bounce. But these are just toys. They don't really do anything. Let's apply these ideas to an actual navigational system, which I've dubbed the bouncy menu. We'll only scratch the surface of what you can do with a bouncy menu, but this exercise will get you started.

Navigation Stretch

With the bouncy menu, you have a horizontal list of items, each of which occupies the same amount of space. When you roll over an item, that item expands and the other items shrink with a wonderful elasticity. You can see an example of the bouncy menu we're about to make.

There are two secrets to how this works: First, when we make the selected item grow, we'll make sure that all of the other items shrink at exactly the right rate. We want the two actions to completely cancel each other out, so the menu as a whole doesn't change in size. The second bit of trickery is that we'll first resize each item and then move them so that they're all aligned with each other. The effect is interesting.

To begin, make a new movie. On the stage, draw a 60-pixel-wide by 15-pixel-high box. Make sure that the actual stroke on the box is a hairline (you can change this in the stroke panel), and delete the lines on the sides of the box so that only the ones on the top and bottom remain. Convert this shape into a button symbol and name it item button. Inside that symbol, change the button's over state so that the box's fill color is different. Now hop back to the main timeline. This is the items' background.

Next, we'll create a new movie clip symbol by selecting Insert, New Symbol. Name it item background. Once you're actually inside item background, drag an instance of item button onto the stage and align it so that the upper left corner of item button is exactly at 0,0. Item background needs to be its own movie clip because we'll be changing its width with our code, and only movie clip instances can be dynamically modified with code.

This background is only part of the actual item movie clip that we'll build next. Select Insert, New Symbol and create a new movie clip symbol named item. Once you're inside of item, drag an instance of item background to the stage and align it so that its upper left corner is exactly at 0,0. Then, open the instance panel, select the item background instance, and name it background.

We need another layer in item to hold the actual text. So create a new layer and then, with it selected, draw a new text field that's wider than the item background clip on the stage. You'll want to change the text to black, 10-point Verdana (in the character panel) and make the text field dynamic. Make sure it's not selectable, and set its variable to text (in the text options panel). Next, align the text field with the background.

Finally, we must give the item movie clip, a linkage ID. A linkage ID is an identifier that lets you dynamically create instances of movie clips with ActionScript. To give item a linkage ID, open the library, right click (ctrl+click on a Mac) on item, and select Linkage. Choose "export this symbol" and make the identifier item. A linkage ID doesn't have to have the same name as the symbol, but I find it tends to be easiest that way.

Now we can start creating the actual code for our menu. First, head back to the main movie and remove the instance of item button we have there. Create a new symbol, a movie clip named bounce menu. After you make it, immediately return to the main timeline and drop an instance of bounce menu onto the stage. This will look like a small white circle. Select it, and open the actions panel. The first bit of code we must add is the code that initializes the menu. Remember that we can only place code that's directly attached to movie clip instances inside of clip events, so we'll be using a load clip event here. Our code appears in Example 2.

NumItems is the number of items we want in our menu. Friction and speedratio are just what they were in our simple bounce code. Boost is how much extra boost speed will be added to selected items, and invboost is how much will be added to unselected items. Base is just the base size of the items' background, the size they'll try to reach.

The for loop simply counts the number of items we want in the menu. The first thing that occurs inside that loop is an attachMovie action that actually pulls our item movie clip out of the library and attaches it to the bounce menu movie clip. (This tells Flash to use the current movie clip, the one to which we're adding code, our instance of bounce menu.) The first argument of the attachMovie action is the actual linkage ID of the movie clip we want. The second argument is the name of the new movie clip instance, and the third is the depth of the instance.

The next few lines all dynamically reference the new movie clip by building its name. In the attachMovie code we named each instance "item"+i, which means that the first instance will be named item0, the second item1, and so on. Now we're telling Flash to look in the current movie clip for an instance named "item"+i. You'll notice that we change three variables: _x, text, and speed. The variable _x, as you know, is just the x position of the movie clip. Text is the actual text that appears in the clip. (Remember the text field we made?) And speed is a variable that all items use to track their current expansion speed.

If you test your movie now, you'll see that you have eight items on the stage all lined up one after the other. Neat, but we want them to bounce! Interestingly enough, you don't need to add much code to make the items elastic. The code in Example 3 will be inside of an enterFrame clip event attached to our bounce menu instance.

The first bit does a fairly simple job: It figures out which items the mouse is currently over (if any). First, the current variable is set to null (basically nothing), and the i variable is set to 0. Then, Flash walks through a while loop until one of two things is false: either current is no longer null or i is equal to the number of items we have in our menu. In each iteration of the loop we perform a hitTest action on the background movie clip of each of our items. If the mouse is over an item, this action returns true, otherwise it returns false. If the item returns true, then we set current equal to that particular item.

Pretty simple so far, right? The next bit is where we calculate the actual elasticity. This for loop walks through each of our items in turn. First, it calculates the speed of the item, just as in our basic bounce code. Then it looks to see if current is set to null, which means the mouse isn't over any of the items. If current isn't null, the code checks to see whether the current variable is equal to the item that the loop is currently checking. If it is, then the Flash plug-in adds boost to the item's speed; if not, Flash adds invboost. Again, boost and invboost are set so that they exactly counteract each other.

Next, the width of each item's background changes when you add the value of this item's speed variable. This is just like what we did with the x position of the simple bounce example. Finally, reposition the current item by finding the previous item's (i-1) x position and adding to it the previous item's background width.

Take Action

That's it. If you test your movie, you'll see how dynamic and fun this menu is!

I suggest that you fiddle with this code quite a bit, and once you're sure you understand how it all works, start coming up with your own additions and modifications. There are infinite possibilities now that you know how to make Flash move, ease, and bounce with code.

(Get the source code for this article here.)


Branden is a senior interactives programmer and instructor at Fig Leaf Software in Washington D.C. He is a contributor to numerous Flash books and speaks at many industry conferences. You can contact him at bhall@figleaf.com.




Copyright © 2003 CMP Media LLC