Tutorial – Object-Oriented Buttons in ActionScript 3

April 22nd, 2011 | 6 Comments

For some people, creating a separate class for a simple button is overkill. However, if you find yourself  reusing the same kind of button over and over, it may behoove you to apply some simple object-oriented ActionScript.

In the last tutorial, I demonstrated how to create an ActionScript 3 Button that didn't rely on the timeline for its animated mouseovers. We're going to create a similar button for this tutorial, but this time, we're going to store the code for the button in a separate ActionScript Class. Let's get started.

Step 1 - Create Your Button Graphics. I'm going to keep things simple and create the same basic button that we discussed in the previous tutorial. Keep the following things in mind as you're preparing the graphics for your button:

  1. Convert your graphics to a Movie Clip symbol with the registration point in the center. As we've discussed before, Movie Clip symbols are much more flexible than Button symbols.
  2. Within your Movie Clip button, put your background graphics inside its own Movie Clip so we can animate the background separate from the text.
  3. Make your text field dynamic (or "TLF Text" if you're using CS5) and embed all uppercase, lowercase, numerals, and punctuation (and anything else you might need) for your font. Give your text field an instance name of label_txt. Later, you will set the text of your button in ActionScript, and you will refer to this instance name in order to do that.

Keep in mind that this time around we're not going to give our Movie Clip button an instance name. Since you're going to attach it to the stage using ActionScript, you just need to create your Movie Clip and then delete it from the stage. (Don't worry, it's still available in your Libary.)

Step 2 - Export for ActionScript. Your next step is to set up your button so that you can access it and attach it to the stage in ActionScript. Find your Movie Clip in the Library Panel, right-click on it, and click on Properties. You will see the following dialog. (If you don't see all the options below, click on "Advanced" in the Symbol Properties dialog.)

Check the "Export for ActionScript" checkbox. This will automatically cause the "Export in frame 1" checkbox to be checked as well, which is what we want.

Flash will automatically populate the field for the Class name with whatever name you gave to your Movie Clip symbol. Edit this name to make sure that the first letter of the class name is a capital letter. The name I'm using here is MCButton. By convention, all class names are capitalized. The name you enter here is very important, so make a note of it. This is the name you will give to your Class when you create it. It's also the name you will use in your ActionScript to attach the Movie Clip button to the stage.

Leave the rest of the options at their default and click "OK" to apply the changes. When you click "OK", a dialog box will pop up and warn you that it can't find the class name you entered. Well, that's what we're about to create, so just click "OK" again, and let's move on.

Step 3 - Create Your MCButton Class. If you've never created your own ActionScript class before, don't worry–it's not as complicated as it sounds. An ActionScript class is simply an external text document that contains ActionScript code in it. The only major differences with external classes is that they have to be structured a certain way, and they require you to import every class you refer to.

To create a class in Flash, go to File > New, and in the popup dialog, select "ActionScript 3.0 Class".

If you're using Flash CS5, then when you click on "OK", you will get another prompt asking you for the name of your class. This needs to be identical to the Class name you assigned to your Movie Clip when you exported it for ActionScript–in this case, MCButton. In CS5, once you enter this class name, your ActionScript class will automatically be set up with the appropriate skeleton code, shown below.

package  {

	public class MCButton {

		public function MCButton() {
			// constructor code
		}

	}

}

If you have an earlier version of Flash, it will take you directly to your AS3 file. Simply copy and paste the code you see above, and then we'll all be on the same page.

Before we move any further, go ahead and save your class file. There are only two things you need to know about saving your class:

  1. Your file name needs to be identical to your class name, capitalization and all.
  2. The file name for an ActionScript class contains the .as extension.

Armed with this knowledge, go to File > Save, and save your file as MCButton.as. (Note: One minor annoyance I've found with editing ActionScript from within the Flash authoring environment is that you don't get popup code hints until you save your ActionScript file; so that's usually the first thing I do when working with external classes.)

Let's take a look at the code we have so far:

In line one, we're putting all of our code within a package. Packages are a little beyond the scope of this tutorial, so for our purposes here, I'll just say that all of our classes will be contained within a package like this.

Within the package declaration is the class declaration. This class is public, which simply means that you can freely access this class from within other classes or other Flash files.

The class declaration as we see it above is still missing a little something. Remember that we're assigning a Movie Clip to this class, and every instance of MCButton that we create is going to require an instance of that Movie Clip. So, in order for this class to be fully effective, it would be nice if our class had all the same properties and methods of the MovieClip class. Well, this can be accomplished through inheritance. All we need to do is tell Flash that we want this class to extend the functionality of the MovieClip class, like so:

package  {

	import flash.display.MovieClip;

	public class MCButton extends MovieClip {

		public function MCButton() {
			// constructor code
		}

	}

}

Notice that two things have changed here. The first change is that we now have an import statement just inside the package declaration. As I mentioned before, every class you reference from within your ActionScript needs to be imported, and our imports will occur before our class declaration but still inside the package.

The second change can be seen within the class declaration. We have added the phrase "extends MovieClip". This tells Flash that we want to inherit all of the functionality of the MovieClip class in addition to whatever other functionality we add within our class. Pretty cool, huh?

Within the class declaration is the constructor function. A constructor is a function that is called automatically whenever a class is instantiated. In other words, if you want something to happen with your button as soon as you place it on the stage, this is where you would put that code. Notice that the constructor function has the exact same name as the class itself. This is required for a constructor function; in fact, that's how Flash knows that it's your constructor. Every ActionScript class will have a constructor, but it won't always have code within it. If there's nothing that needs to happen when you place your constructor on the stage, then you would just leave your constructor empty. For a Movie Clip button, however there are a couple things we need to include here. For example, whenever we place our buttons on the stage, we want them to act like buttons. In other words, we need to add our mouse listeners here, because as soon as we instantiate our buttons, we want them to start listening  for mouseovers and any other events we might need.

Here is our updated constructor function:

public function MCButton() {
	// constructor code
	this.buttonMode = true;
	this.addEventListener(MouseEvent.MOUSE_OVER, hover);
}

First of all, since you're using a Movie Clip symbol and treating it like a button, you need to turn buttonMode on. Now, when you hover over it, you will see the hand cursor that you expect to see when hovering over a button or a link. Secondly, you're creating your mouseover event using the addEventListener() method.

Remember that when you're dealing with external classes, you must import every single class you use within that class. (Anything that starts with a capital letter is usually a class.) Since we're referring to the MouseEvent class here, be sure to add the following code just below where you imported the MovieClip() class:

import flash.events.MouseEvent;

If you tried to test everything right now, you would get an error, because our event listener is currently referring to a function that doesn't exist yet: namely, the hover function. Let's create that now. Enter the following code just below the closing curly bracket of the MCButton constructor function, but still within the curly brackets for your package and class:

private function hover(e:MouseEvent):void {
	this.removeEventListener(MouseEvent.MOUSE_OVER, hover);
	this.addEventListener(MouseEvent.MOUSE_OUT, out);
	Tweener.addTween(this.bg_mc, {scaleX:1.5,time:0.5,transition:"easeOutElastic"});
}

private function out(e:MouseEvent):void {
	this.removeEventListener(MouseEvent.MOUSE_OUT, out);
	this.addEventListener(MouseEvent.MOUSE_OVER, hover);
	Tweener.addTween(this.bg_mc, {scaleX:1,time:0.5,transition:"easeOutElastic"});
}

Once we hover over the button, we no longer need to listen for the MOUSE_OVER event, so inside the hover() function, remove this listener. Then, you will add the MOUSE_OUT listener, which will trigger the out() function, seen below the hover() function.

After adding the MOUSE_OUT listener, we're calling on the Tweener class (click here for more info) to animate the width of the bg_mc Movie Clip within our button. This (bg_mc) is the instance name I gave to the background of the button. And once again, since we're calling on an external class, it's time for another import statement, just below your last one:

import caurina.transitions.*;

Another thing you might have notice in your code is the constant use of the word this, which simply refers to the button object itself. When we reference the Tweener class, for example, you'll see that I have made a reference to this.bg_mc, which refers to the background Movie Clip within the current button Movie Clip.

Step 4 - Add an MCButton to the Stage. For all intents and purposes, you now have a fully functional ActionScript 3 class. Easy enough, right?

Jump back over to your FLA file, and if you still have a button on your stage there, get rid of it. We're going to add a button now using ActionScript.

Once your stage is clear, click on frame 1 in your timeline and hit F9 (or Option+F9 on a Mac) to open up your Actions Panel. Enter the following code:

var btn1:MCButton = new MCButton();
btn1.x = 150;
btn1.y = 50;
addChild(btn1);

To create a new button, the first thing you need to do is to create a variable in which to store it. This is taken care of in the first line, where you create a new instance of the MCButton() class and store it in a variable called btn1.

In the next two lines, set the x and y coordinates of your button (your coordinates might be different than mine), and then add your button to the stage using the addChild() method.

Voila! If you've installed the Tweener class properly (and entered the code correctly), then you now have your own object-oriented button class.

However, we're not finished yet. One of the advantages of this object-oriented approach is the ability to customize each instance of your button without having to enter a bunch of extra code.

Can you see something that could use some customization?

Step 5 - Changing Your Button Labels. As it stands, every button you place on the stage is going to have whatever default text you entered into your text label. Well, we didn't make our text field dynamic just for the fun of it, so let's take a look at how we can customize our labels.

The most obvious method is to customize your label within the ActionScript for your FLA file. So, instead of the above code, you would have something like this:

var btn1:MCButton = new MCButton();
btn1.x = 150;
btn1.y = 50;
btn1.label_txt.text = "home";
addChild(btn1);

The most dynamic way would actually be to create your text field dynamically from within your class file, but that's a little beyond the scope of this tutorial. For our purposes here, let's just stick with the code we have so far. So if you wanted three different buttons using your fancy new MCButton class, you might use the following code:

var btn1:MCButton = new MCButton();
btn1.x = 150;
btn1.y = 50;
btn1.label_txt.text = "home";
addChild(btn1);

var btn2:MCButton = new MCButton();
btn2.x = 150;
btn2.y = 100;
btn2.label_txt.text = "about";
addChild(btn2);

var btn3:MCButton = new MCButton();
btn3.x = 150;
btn3.y = 150;
btn3.label_txt.text = "contact";
addChild(btn3);

Now you have a fully functional, object-oriented, ActionScript 3 button that can be duplicated with only a couple lines of code. And just for your reference, here is the final ActionScript 3 class file:

package  {

	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import caurina.transitions.*;

	public class MCButton extends MovieClip {

		private var btnLabel:String;

		public function MCButton() {
			// constructor code
			this.buttonMode = true;
			this.addEventListener(MouseEvent.MOUSE_OVER, hover);
		}

		private function hover(e:MouseEvent):void {
			this.removeEventListener(MouseEvent.MOUSE_OVER, hover);
			this.addEventListener(MouseEvent.MOUSE_OUT, out);
			Tweener.addTween(this.bg_mc, {scaleX:1.5,time:0.5,transition:"easeOutElastic"});
		}

		private function out(e:MouseEvent):void {
			this.removeEventListener(MouseEvent.MOUSE_OUT, out);
			this.addEventListener(MouseEvent.MOUSE_OVER, hover);
			Tweener.addTween(this.bg_mc, {scaleX:1,time:0.5,transition:"easeOutElastic"});
		}

	}

}

And here's a look at the final output:

Related Post: ActionScript 3 Tutorial - Tweener Transitions

Tags: , , , , , ,

6 Responses

  1. Jernej says:

    Wow awesome! Thanks for this :)

  2. [...] See the rest here: Tutorial – Object-Oriented Buttons in ActionScript 3 [...]

  3. Ros says:

    Access of possibly undefined property bg_mc through a reference with static type MCButton.

  4. Agilis says:

    Thank you for this wonderful tutorial! If I were to have buttons that are different widths, without making a bunch of different size symbols, how would I make it so that the button’s background stretches to fit the button’s label’s width?

  5. Zac says:

    ReferenceError: Error #1056: Cannot create property bg_mc on MCButton.
    at flash.display::Sprite/constructChildren()
    at flash.display::Sprite()
    at flash.display::MovieClip()
    at MCButton()
    at hazteszt_3_fla::MainTimeline/frame1()

    What’s wrong. I need some help.

    Thx

  6. LexF says:

    Thanks for the tutorial …

    How can i apply this exact class to a MovieClip on stage rather than via AS Linkage?

    … All my best!

    Lex

Leave a Reply