Build a Versatile ActionScript 3.0 Menu with Masking

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.

Add Comment

Discussion 48 Comments

Comment Page 2 of 2 1 2
  1. Amanda says:

    doesn’t work in IE8

  2. Marvin says:

    tricky over zone of the mouse :>
    but great work

  3. Philo says:

    It works in FF, but is delayed, i takes some time before the other buttons on the right side show.

  4. Amanda says:

    You shouldn’t be advertising that this is AS3 and then doing most things on the timeline… especially when what you are doing on the timeline can easily be done with code… come on now..

  5. There are some holes in the menu…the rollover menu keeps opening and closing because of the hit states in the demo. I like the overall idea of this tutorial but the demo could have been made better.

    Shouldn’t we re-frame from using timeline animation?

  6. JoeK says:

    im suprised by the lack of Document Classes in these tutorials

  7. Is very simple, sometimes doesn’t work correctly.

  8. Zack says:

    Can anyone post anything on flashtuts? Someone should be monitoring the tutorials to make sure they are high quality, and work without flaws. The idea is great but the execution is weak.

  9. john says:

    Boy! some real ass moaners, that leave comments on the flash.tuts

    Anyway, my comment.

    Thanks for the tutorial, I’ll work through it and once I get my head around it. I’ll take my new found knowledge and apply it to a project.

  10. Bruno says:

    Is a good effort men. Go ahead and never give up :)

  11. David B says:

    The demo doesn’t work very well.

  12. Anselmo says:

    Nice tut, but this can be done with jquery with less code.
    Good work though!

  13. shampi says:

    wow that’s kinda tricky…you could easily do this only with code. Why using the timeline… You use as3 but think in as2 :(

    But good effort anyway ;) keep trying! thx.

  14. not stable enough really. Quite a few bugs.

  15. samBrown says:

    diggin it, thx for the post.

  16. keruchan says:

    have some bugs but it can be fix by simple tweaks.

  17. Author

    cheers for all constructive comments: can you layout what bugs? i tested it but don’t encounter anything weird, infact, it works like a train here.
    But i am open for suggestions and learn even myself. I can rewrite certain parts. About the IE thing: everything works okay here. so please share a light on the bugs.

    to the others, this tutorial was made over in discussion with the editor of flash tuts.we both wanted to capture the code & timeline part so people with no AS 3 background could easily step in. Document classes, full on code based tutorials are different topics.

  18. moih60 says:

    amazing one..i just interested in flash so ur site is amazing for me
    thanx and added to my blog

  19. lawrence77 says:

    we mouseover home for the first time, it disappears suddenly! :(

    some bugs are there, anyway good tutorial!

  20. René Flores says:

    I love tuts+ tutorials, but this flash section is definitely lacking, and this tutorial is horrible, anyone with a little flash knowledge and some common sense could of had figured it out.

    Instead of explaining how to use buttons, and timelines, tutorials should be about proper use of actionscript.

  21. Author

    René, as said before, along side the editor of flashtuts, we decided to make a step in tutorial, as they get alot of requests for beginner tutorials. so here goes.

  22. Steve Jabs says:

    Meh. No one should ever teach flash navigation for websites. The lack of all SEO with this makes me shudder.

  23. Cool tutorial. Keep coming these kind of tutorials. Thanks for sharing such a useful tutorial.

  24. rok says:

    good,,,,, nice work :))

  25. Franky says:

    Awesome Tutorial. Im going to get on this right now!!!

  26. wh says:

    Thank u Peter..good.work..looking forward better work..

  27. saki says:

    Very Informative & helpful Tutorial

  28. Pat says:

    I’m surprised this tutorial got past quality control, this is poorly communicated and the technique is cumbersome at best. Good idea but hard to follow.

  29. I love the amount of details you gave in your instructions through this tutorial. Great example. Looking forward to more from you.

  30. mayareactor2 says:

    CORRECTION: TweenMax [and the full greensock tween library] was written by Jack Doyle, not Grant Skinner, as indicated in STEP 6 of this demo.

    Grant Skinner only recently joined forces with Jack; Grant Skinner is responsible for creating gTween, not TweenMax.

    http://blog.greensock.com/gskinnercollaboration/

  31. yogie christian says:

    how about if i wanna when the button clicked . .it go to another frame not to another external swf?
    im very confused…

    anybody, help?

  32. jmarreros says:

    it’s no so impressive, I think the code could be better. thanks anyway

  33. Sharedtut says:

    this is very good but not the best method

  34. Adam James says:

    Cant seem to import the tween classes! I’m going to the settings panel in file/publish settings and locating the greensock file with all the classes inside it but when I export the flash says it cant locate the classes!

    I looked at the AS and the import path for tween max is “gs.tweenmax” does this mean the file name of the tween classes needs to be changed to “gs” ???

    A little help with this would be much appreciated :)

    Many Thanks (Tutorial has been really good so far)

    Adam

    • Peter says:
      Author

      Sorry for the awesome late reply, too bad we don’t get updates on this messaging system.
      but…

      Could you post what the exact error is? Assuringly since the package of greensock is changed you willl need to import the classes as com.greensock.*

      But its hard to say like this, contact me through my site / email and i’ll see how I can help out with the file.
      Best regards
      Peter

  35. gfelice says:

    Any chance you could give us the code to load the first page when the site loads, so you don’t have to click the nav to get your first page to load?

    • Nit'ras says:
      Author

      Hi,

      Everything is there.

      You can take the isLoaded function, rename it to firstPageLoadingor so.
      And hardcode the currentPage to your swf that you want to load.
      This should work

      function firstPageLoading():void
      {

      var currentPage:String = “myfirstswftoload.swf”;
      //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 ();
      }
      }
      //trigger this new function
      firstPageLoading();

  36. RDude says:

    this tutorial looks nice but is totally unusable,
    too many bugs:

    - loaderclip is not called by the AS code = nothing gets loaded
    - navigation is buggy, doesn’ t respond well
    - string array doesn’t convert well to external SWF load
    etc.

    please upload a working set of FLA and correct your tutorial, its faster to create an own navigation rather then waste my time fixing your bugs

    Thanks for the attempt!

  37. wiyono says:

    Hallo..
    Tha is so great..
    Can you tell me how to make transition page?
    And i have problem with loading… the preloader sometimes don’t go… and stop… what the problem about that?

    Sorry my English not good
    Thank you

  38. nallavan says:

    this tut takes much time to load . so we lack our interest . u should reduce the bites of details.

  39. Julien says:

    Thanks, it helps me a lot and works great !

  40. Jazokas says:

    Yessss!!!!!
    At last I found it! How to make active button,damn.

    I will use in my portfolio.

    thank you again!:)

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.