3. Writing the Expander Class

With your fla file still open, go to File, New. Open a new Actionscript File. Type the following into the script pane:

package com.mysite.effects {
    import flash.display.MovieClip;
 
    public class Expander {
        private var _clip:MovieClip;
 
        public function Expander(clip:MovieClip) {
            _clip = clip;
        }
    }
}

Choose file, Save As. In the "Save As" dialog box, navigate to the com/mysite folder, create a new folder called "effects," enter that new folder, and save the file there as "Expander.as." Hopefully you did the last tutorial and you already have the "com" and "mysite" folders arranged underneath a classpath folder. If not, check out my first tutorial, and make sure you understand the classpath and how to make packages, and then come back. This is not to imply that it must be done this way or it won't work, of course. I just want to make sure you understand that you can store your classes in your own packages and then import them at will. Once you have the hang of it, you can then name your folders whatever you want, and organize it your way. In fact, I recommend it!

The basic structure above is the same thing we started with last time. To review, we know that we must import the MovieClip class, as we'll be passing in our "help" MovieClip as a parameter. The constructor of the class sets a private variable, "_clip" to be equal to the clip that we pass in. That way, our passed-in MovieClip becomes a property of our class.  This is all the same stuff we did before.

What we're going to do, naturally, is cause the clip to expand when it's clicked on with the mouse, and then collapse when it's clicked again. We purposely crafted the MovieClip with two different frames so that we could switch frames just before we expand it. This way, the collapsed clip can bear a different message than the expanded one, and all we have to do to change frames is use the "gotoAndStop()" method on our "_clip" property, which now refers to the same MovieClip instance that's on the stage.

We know that we're going to need to use mouse events, and I've also told you that we're going to use the Tween class to animate the help box. So, we'll import the Tween class, the TweenEvent class, and all the easing classes. Add these lines to the import statement block:

import flash.events.MouseEvent;
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;

There are several things to note here. First is that many of these classes and packages are in "fl" instead of "flash." All I can say is that if you don't know the location of a class, consult the help files (the "code hints" popup also helps quite a bit). Also new here is the use of the (*) to import an entire package at once. When you see an asterisk in an import statement, just think "all classes." This one statement will import all the easing classes in that package. You need not worry that they won't all get used, either; the compiler is smart enough to just include the ones you actually use. But importing them all means that we can change easing methods and recompile without changing the import statement every time. Finally, there's the TweenEvent class, and I just wanted to note here that it isn't located in the flash.events package, as you might think.

With all those classes imported, we can go on and write the class. First, we'll create a bunch of variables of the Number datatype. We're going to Tween the height, width, and alpha properties of our MovieClip, so the six variables will represent those values (add all these to the variables list, right after the "_clip" one):

private var _startWidth:Number;
private var _endWidth:Number;
private var _startHeight:Number;
private var _endHeight:Number;
private var _startAlpha:Number = 0.2;
private var _endAlpha:Number = 1;

The reason _startAlpha and _endAlpha are given values right in the varible list is so that we can start with some kind of default values for those. The others will be given default values in the constructor, which we'll turn to next. Change the constructor so that it reads like this:

public function Expander(clip:MovieClip) {
    _clip = clip;
    _startWidth = _clip.width;
    _startHeight = _clip.height;
    _clip.gotoAndStop(2);
    _endWidth = _clip.width;
    _endHeight = _clip.height;
    _clip.gotoAndStop(1);
    _clip.buttonMode = true;
    _clip.addEventListener(MouseEvent.CLICK, expandMe);
    initClip();
}

 This utilizes a cool little trick. First, the _startWidth and _startHeight properties are set equal to the width and height of the _clip itself. This is the width and height of the clip as it sits stopped on frame 1. Then, we tell the _clip to gotoAndStop(2) so that we can read the width and height again. These values will be different, because when the _clip is stopped on frame 2, it's wider and taller than when it's on frame 1. This way, we can capture a default _endWidth and _endHeight to use. Then we put the _clip back to frame 1 again. We set buttonMode to true to get a hand cursor, and add an event listener to respond to a mouse click. At this point, we have yet to write the expandMe function, and we'll get to that. But first, let's write the initClip function referred to in the last line. Here is is:

private function initClip() {
    _clip.width = _startWidth;
    _clip.height = _startHeight;
    _clip.alpha = _startAlpha;
}

 All this does is further initializes our MovieClip. This might not make sense to you at first. We just finished setting our variables equal to the _clip's width and height, and now we turn around and do the reverse! The only thing that seems to really get done here is setting the _clip's alpha. However, there's a good reason for separating these lines from the constructor. Later, when we make our setter functions, we can call initClip again to re-intialize the _clip so that it resizes.

Before we move on to write the expandMe and contractMe functions, let's add five more variables to the variables list:

private var _easing:Function = Bounce.easeOut;
private var _duration:Number = 2;
private var twWidth:Tween;
private var twHeight:Tween;
private var twAlpha:Tween;

This gives us one convenient place where we can change the _easing method and the _duration of the animation. Changing it here is easier than changing it in all the six other places we're going to be using it!

Finally, there's the three Tween variables, named after the properties that they'll be operating on. I didn't deem it necessary to precede these names with an underscore, as we won't be manipulating them with getters and setters, which is where I think underscores come in handy (to distinguish the names, as you'll see). Also, if you work with the Tween class, you soon find out the hard way that these variables need to be declared outside the function that uses them, otherwise they can get "garbage collected" and your animations won't behave right. This is an issue new to Actionscript 3.0. Take my word on this one.