Advertisement

Build a Versatile ActionScript 3.0 Menu with Masking

by

Navigation is a crucial part of your website, but often a bore to build and maintain. In this tutorial I'll describe a quick and solid way of using basic ActionScript skills, blended with a bit of your creativity, to construct intuitive & user friendly navigation systems. Okay, time to get our hands dirty, well... sweaty maybe...

Introduction

This tut demonstrates how to prevent double-clicking items within the menu, a much overlooked item that enhances your online experience. You'll also learn how to create and combine multiple arrays with ease. First we'll layout the scene, place keyframes and labels, then at the end we'll add some ActionScript to make it come alive. We'll also learn how to create page transitions which add a nice little extra to your website.

In retrospect, this tutorial is very simple, but it covers a lot of hidden gems. Be creative, link the data with xml, alter the mask shapes, change the button rollOver states and enjoy it.

Step 1 : Preparing the Buttons

Create a new ActionScript 3 document : 600px X 400px, 30frames per second and use white as a background. First things first, lets create the button. Draw a textbox on stage and give it an instance name of "txt". To do this go to your properties panel (CTRL F3 / Window > properties > properties). Now covert it into a symbol (F8 / Modify > Convert to Symbol), choose movieclip and make sure the registration point is at the top left. Name the instance "button_text_mc".

On a new layer, make a rectangle which fits the boundings of your text movieclip. This will function as a hit area for your button. Convert it into a symbol.

Now select both layers and convert them into a symbol. Name this instance "hitarea_mc". Make sure you put the alpha value of "hitarea_mc" at zero in the properties window.

Step 2 : Placing the Buttons

Now let's make a holder for our buttons. Of course you can make this more advanced by making this a full dynamic navigation with xml or php, but for the sake of this tutorial we'll use
some ActionScript to name our menu items and fill in the functionality.

Drag one instance of the movieclip "button_movieclip" on stage for each item you want for your navigation. We'll use 6 in this case. Now give each instance a unique name; I chose b1,b2,... up to b6. Next we're going to wrap this all up in a new movieclip named "menu_total".

The good thing about this is, if we want to use it later on we can simply drag the "menu_total" clip out of the library and use it directly. You should now have a single movieclip on stage holding six buttons which we'll transform into our navigation.

Step 3 : rollOver/rollOut States on the Timeline

Aah the fun part. Some animation and trickery. As you see in the example, the menu only reveals itself when the mouse cursor moves near the menu box and line. To achieve this, we'll need an invisible hitarea and some keyframes to move to a different state of view.

Make sure you are inside the "menu_total" movieclip and create 2 new layers at the very top of your layers: one named "code", the other named "labels". Select the "labels" layer and add a blank keyframe on frame 1, 2, 10, 24, 25, 37. Now name the second framelabel "CLOSED", the 10th framelabel "OVER" and the 25th framelabel "OUT".

Create a new layer underneath the buttons layer and name it "hit_area", then take the movieclip "hitarea_mc" from your library and place it to the left of the buttons. Lastly, rescale it so the user has some room to move the mouse. Make sure the keyframes for "HOVER" only reach to frame 10.
Create yet another layer and name it "menu_out", then go to frame 10 and place another copy of the "hit_area_mc" on stage. Give it an instance name of "HOVEROUT_MC" and make sure that both these movieclips have an alpha value of 0. Also, these two hit area movieclips need to overlap a bit. Otherwise Flash will lose the hit test when you move the mouse towards the buttons.

OK, with all that done, your frames and labels should now look like this:

This is how the hit areas for the mouse should look:

This is what the second hitarea should look like: it starts on the keyframe of the over state.

Now let's take a look at the masking.

Step 4 : Add the loaderimage Movieclip

Across the span of your animation for the rollOver/rollOut states, make an empty movieclip and give it an instance name of "loaderclip".

Step 5: Prepare Your External SWF Files

This bit's entirely up to you and your imagination, but here's a basis which should get you started. Create a new ActionScript 3.0 file with the same dimensions as your main file. Build your page in/out animation. Make sure you place a stop(); command at the end state of your animation (the place where the actual content will come). Save your files as page1.swf, page2, ... up to the amount of buttons you created, in this case 6.

In my utterly simple example I started with a small box which tweens along the timeline from alpha 0 to 100 whilst it grows to its final height.

Step 6 : Action!...But Wait...

Right, now some ActionScript time. First of all, you can spice up whatever happens with the menu however you wish. For example, you could use more advanced rollOver/rollOut animations.
For the sake of this tutorial I've chosen a very simple effect.

You will need to download and import the opensource class built by Grant Skinner named "tweenmax". Make sure you download the AS3 version. We'll also use the built in classes for the transitions.

Step 7 : Action!...Are You Sure? - Yep!

With your code layer selected on frame one, enter the code in the following steps (I will explain each line in the comments).

Note: from this point it's very easy to make a new array with all your actions and link it to the onRelease handler, the same way as you link the buttonnames to the actual movieclips. With minimal effort you can build a very strong navigation system that can be reused over and over in no time. You could build a class for this, but that's not the purpose of this tutorial.

Step 8: Action!...Imports

import gs.TweenMax;import fl.motion.easing.*;import fl.transitions.*;import fl.transitions.easing.*;

Step 9: Action!..Variables

//variables for the button rollover,out,hit state
var speed:Number = 0.3;var motion:Function = Sine.easeOut;var colourOver:String = "0x9BE07C";var colourOut:String = "0x000000";var colourRelease:String = "0xFF0000";
//store the buttons as an object for later use or reference.
var btn:Object;var disabledBtn:Object;
//The currentPage,nextPage variable holds the movieclips we will load.
var currentPage:MovieClip = null;var nextPage:MovieClip = null;
//the loader
var loader:Loader;
//which movieclip to load
var urlRequest:URLRequest;
//the name for our menu
movieclip.MENUNAME.txt.text = "MENU >";

Step 10: Action!..Set Up Arrays With Our Data

//first we'll reference to all the buttons on the stage
var buttons:Array = new Array (b1, b2, b3, b4, b5, b6);
//this array holds all the names we want to use for our buttons
var button_name:Array = new Array ("Home", "About Us", "Selected Work", "References", "Jobs", "Contact");
//this array stores which swf we want to load
var swf_array:Array = new Array ("swf1.swf","swf2.swf","swf3.swf","swf4.swf","swf5.swf","swf6.swf");

Step 11: Action!...Loop Through the Button Array

for (var i:String in buttons)
{
	//assign the button_name array to the textclip of our buttons
	buttons[i].button_txt.txt.text = button_name[i];
	//assign which swf we'll load for each of the buttons
	buttons[i].currentPage = swf_array[i];
    //declare that we'll use the movieclip as a button
	buttons[i].buttonMode = true;
	//make sure that the button_txt clip doesn't react to the mouse	
    buttons[i].button_txt.mouseChildren = false;
	//add the listeners for our buttons	
    buttons[i].addEventListener (MouseEvent.CLICK,onCLICK);
	buttons[i].addEventListener (MouseEvent.MOUSE_OVER,onOVER);
	buttons[i].addEventListener (MouseEvent.MOUSE_OUT,onOUT);
}

Step 12: Action!...EventListeners:

function onCLICK (event:MouseEvent):void{	
//make sure the variable of our current target is stored, we'll adress it later on to the function to disable it's state		
btn = event.currentTarget;	disableBtn (btn);};function onOVER (event:MouseEvent):void{	btn = event.currentTarget;	
//here we tween to the over color we've assigned earlier on with the variables.	
TweenMax.to (btn , speed , {tint:colourOver, ease:motion});};function onOUT (event:MouseEvent):void{	btn = event.currentTarget;	TweenMax.to (btn , speed , {tint:colourOut, ease:motion});};

Step 13: Action!...Build the Machine!

This is the main core of our project. Every important step is commented in the code.

function disableBtn (btn:Object):void
{
	//if the button is disabled we'll make sure every event is back in it's place so we can use it again
	if (disabledBtn)
	{
		disabledBtn.buttonMode = true;
		disabledBtn.mouseEnabled = true;
		TweenMax.to (disabledBtn , speed , {tint:colourOut , ease:motion});
		disabledBtn.addEventListener (MouseEvent.CLICK,onCLICK);
		disabledBtn.addEventListener (MouseEvent.MOUSE_OUT,onOUT);
		disabledBtn.addEventListener (MouseEvent.MOUSE_OVER,onOVER);
	}
	TweenMax.to (btn , speed , {tint:colourRelease , ease:motion});
	//disabling means not being able to use it anymore, so here we remove all functionality	
    btn.buttonMode = false;
	btn.mouseEnabled = false;
	btn.removeEventListener (MouseEvent.CLICK,onCLICK);
	btn.removeEventListener (MouseEvent.MOUSE_OUT,onOUT);
	btn.removeEventListener (MouseEvent.MOUSE_OVER,onOVER);
	//make sure the current selected button is labeled as disabledBtn.
	disabledBtn = btn;
	//Create a new loader instance
	loader = new Loader();
	//add the currentPage variable to the url request	
    urlRequest = new URLRequest(btn.currentPage);	
    //load the url request
	loader.load (urlRequest);	
    //once the file has been loaded we'll trigger the fileLoaded function
	loader.contentLoaderInfo.addEventListener (Event.COMPLETE, isLoaded);
}

function isLoaded (event:Event):void
{

	//The loader now contains the page we are going to display later on
	nextPage = event.target.content;
	//check if there is a currentPage
	if (currentPage != null)
	{
	//tween the alpha to zero
	//so wait...why are we using 2 different tweenclasses? well, just to show you the benefits and disadvantages of both. Decide for yourself which one you find most suitable for your projects.
		var tweenAlpha:Tween = new Tween(currentPage, "alpha", Regular.easeOut, 1, 0, .7, true);
		
	//additionally, you can make the currentPage perform an extra outgoing animation. Make sure you toy around with the length of your alpha so it doesn't dissapear before the animation is done.
    	currentPage.gotoAndPlay (31);
		//currentPageGone will be called when the tween is finished
		tweenAlpha.addEventListener (TweenEvent.MOTION_FINISH, currentPageOut);
	} else
	{
    	//if there is no currentPage we'll trigger the showNextPage function.
		doNextPage ();
	}
}

function doNextPage ():void
{
	//position the loaderclip as nextPage
	nextPage.x = 238.0;
	nextPage.y = 0;
	//Tween the alpha from 0 to 1
	var tweenAlpha:Tween = new Tween(nextPage, "alpha", Regular.easeOut, 0, 1, .3, true);
	//Add the next page to the stage
	addChild (nextPage);
	//Next page is now our current page - confusing? It isn't. We replace the next page with our current one.
	currentPage = nextPage;


}
//Once the animation is completed we'll trigger this function
function currentPageOut (event:Event):void
{
	//Remove the current page completely from the stage
	removeChild (currentPage);
	//Let's show the next page
	doNextPage ();
}
//don't place a stop command because we will directly land on frame 2.

Step 14: Action!...HitTest For Menu Open

Finally, we move up one frame. Make sure you're at frame 2 of the menu_total movieclip.

//add an eventlistener for the mousemove
HOVER.addEventListener(MouseEvent.MOUSE_MOVE, openmenu); 
function openmenu(e:Event):void
  	{	
        //when the mouse x & y values is inside the movieclip clip named "HOVER", the hittest is true	
        HOVER.hitTestPoint(parent.mouseX, parent.mouseY, true)	{
        gotoAndPlay("OVER");	
        //make sure we remove the listener so we can't trigger this by accident.	
        HOVER.removeEventListener(MouseEvent.MOUSE_MOVE, openmenu); 	}
}stop();

Step 15: Action!...HitTest For Menu Out

Now move over to frame 24 of the menu_total movieclip.

//add an eventlistener for the mousemove
HOVER_OUT.addEventListener(MouseEvent.MOUSE_MOVE, menuout); 
function menuout(e:Event):void
	{	
        //when the mouse x & y values is inside the movieclip clip named "HOVER_OUT", the hittest is true	
        HOVER_OUT.hitTestPoint(parent.mouseX, parent.mouseY, true)	{	gotoAndPlay("OUT");
        //make sure we remove the listener so we can't trigger this by accident.	
        HOVER_OUT.removeEventListener(MouseEvent.MOUSE_MOVE, menuout); 	}
}stop();

Step 16: Action!...Go To "Closed" Frame:

On the last frame of your animation, simply set the following line of code. The reason being that we skip frame 1 so the menu doesn't load again thus losing the active/disabled state.

gotoAndStop("CLOSED")

Conclusion

So there we are! You learned how to enable/disable clicked buttons in an array with combined data, use masking techniques and how to create simple but effective menu systems which can be reused with minimal effort. All this with a simple but effective page transition. I hope you enjoyed this one and found a practical way to speed up your workflow in Flash.

Advertisement