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 schoolphysics. Now, stop shaking in your boots so we can get started. It's not as scary as you think.
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:
_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?
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:
goal = 500;
_x += (goal - _x) / 2;
The new clip event,
load, runs only oncewhen 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.
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 percentagethis 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 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
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.
Sowith just a little codewe 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.
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
NumItems is the number of items we want in our menu.
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.
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:
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
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
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 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.
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 email@example.com.