flash interactivity_dynamic_menu
Creating a dynamic menu
All Flash applications or sites have to have a way of navigating allowing the user to navigate through the content. The menu is one of the key elements of a site or application and we have all developed a menu at least once.
ActionScript 3 has various interesting improvements so we will now create a dynamic menu to see these using the button that we created in the previous article.
Our menu will work vertically so let’s start by instantiating each instance in a for loop:
// creation of a container var container:Sprite = new Sprite(); container.x = 20; addChild ( container ); function createMenu ():void { var lng:int = 5; var myButton:Button; for ( var i:int = 0; i< lng; i++ ) { // creation of instances of the button symbol myButton = new Button(); // variable referencing the clip used for the upState var upState:MovieClip = MovieClip ( myButton.upState ); // modification of clip for all states myButton.upState = upState; myButton.downState = upState myButton.overState = upState myButton.hitTestState = upState // arrangement of instances myButton.y = 20 + i * (myButton.height + 10); container.addChild ( myButton ); } } createMenu();
By testing our code, we get the following result:
During the for loop we move each Button in the menu thanks to the value of the variable i which is incremented. By multiplying the height of each occurrence by i we get a y position specific to each Button.
Very often a menu is dynamically generated by external data coming from a local array, a local XML file or data coming from a server. We are going to modify the previous code by defining an array containing the name of sections to show in the menu.
The number of Buttons in the menu will be based on the number of elements in the array:
// sections var captions:Array = new Array ( "Homepage", "Photos", "Links", "Contact" ); // creation of a container var container:Sprite = new Sprite(); container.x = 20; addChild ( container ); function createMenu ():void { var lng:int = captions.length; var myButton:Button; for ( var i:int = 0; i< lng; i++ ) { // creation of instances of the button symbol myButton = new Button(); // variable referencing the clip used for the upState var upState:MovieClip = MovieClip ( myButton.upState ); // modification of clip for all states myButton.upState = upState; myButton.downState = upState myButton.overState = upState myButton.hitTestState = upState // arrangement of instances myButton.y = 20 + i * (myButton.height + 10); container.addChild ( myButton ); } } createMenu();
Our menu is now based on the number of elements of the array, if we take or add elements to the array source data, our menu is updated automatically. In order for each Button to display a specific caption we get each value contained in the array and input it into each textfield contained within the Buttons.
We can easily get the array content in the loop thanks to the square bracket syntax:
function createMenu ():void { var lng:int = captions.length; var myButton:Button; for ( var i:int = 0; i< lng; i++ ) { // creation of instances of the button symbol myButton = new Button(); /* displays : Homepage Photos Links Contact */ trace( captions[i] ); // variable referencing the clip used for the upState var upState:MovieClip = MovieClip ( myButton.upState ); // modification of clip for all states myButton.upState = upState; myButton.downState = upState myButton.overState = upState myButton.hitTestState = upState // arrangement of instances myButton.y = 20 + i * (myButton.height + 10); container.addChild ( myButton ); } }
We target the textfield in the loop and we give it its content:
function createMenu ():void { var lng:int = captions.length; var myButton:Button; for ( var i:int = 0; i< lng; i++ ) { // creation of instances of the button symbol myButton = new Button(); // variable referencing the clip used for the upState var upState:MovieClip = MovieClip ( myButton.upState ); // modification of content upState.myCaption.text = captions[i]; // modification of clip for all states myButton.upState = upState; myButton.downState = upState myButton.overState = upState myButton.hitTestState = upState // arrangement of instances myButton.y = 20 + i * (myButton.height + 10); container.addChild ( myButton ); } }
In testing the previous code we get the following result:
Our menu is finished. We could leave it there but it lacks a bit of life. We will now spice it up by adding movement. With a slide effect we will make it more attractive and also learn about creating movement through programming.
Adding movement with programming
In order to create different movements we will use algorithms, different opensource libraries or even the Tween class integrated in Flash CS3.
The Tween class lives in the f1.transitions package and should be imported in order to be used. In order to give movement to a graphic object in Flash we can use the Event.ENTER_FRAME or TimerEvent.TIMER events.
The Tween class uses an Event.ENTER_FRAME event at its interior in order to modify the property of the object. A large number of movements are available, they can be kinetic, elastic they can bounce or simply be smooth and constant.
We are going to add an elastic effect to our menu and to do this we will allocate a Tween object to each Button instance. Each reference to the tween object is stored in the Button instance to be able to get at them more easily later on.
The Tween class is not automatically imported for the compiler, we therefore need to do it in order to use it.
We listen to the MouseEvent.CLICK Button events:
// importing the Tween and Elastic classes for the movement import fl.transitions.Tween; import fl.transitions.easing.Elastic; // sections var captions:Array = new Array ( "Homepage", "Photos", "Links", "Contact" ); // creation of a container var container:Sprite = new Sprite(); container.x = 20; addChild ( container ); function createMenu ():void { var lng:int = captions.length; var myButton:Button; for (var i:int = 0; i< lng; i++ ) { // creation of instances of the button symbol myButton = new Button(); // variable referencing the clip used for the upState var upState:MovieClip = MovieClip ( myButton.upState ); upState.myCaption.text = captions[i]; // modification of clip for all states myButton.upState = upState; myButton.downState = upState myButton.overState = upState myButton.hitTestState = upState // arrangement of instances myButton.tween = new Tween ( myButton, "y", Elastic.easeOut, 0, 20 + i * (myButton.height + 10), 3, true ); container.addChild ( myButton ); } } createMenu(); // capture of the MouseEvent.CLICK event in the container.addEventListener container ( MouseEvent.CLICK, clickMenu, true ); function clickMenu ( pEvt:MouseEvent ):void { // displays : [object Button] trace( pEvt.target ); // displays : [object Sprite] trace( pEvt.currentTarget ); }
The position of the Y axis of each button is managed by our Tween object. By storing each Tween object created in the Buttons we can make reference to them at any moment by targeting the Tween property.
Our menu deploys with an elastic effect and becomes much more interactive. We are not restricted to a single movement, we can further by adding a similar effect on rollover. This time, the movement will be done on the width of the buttons.
We store a new instance of the Tween class to manage the rollover effect of each Button:
// importing the Tween and Elastic classes for the movement import fl.transitions.Tween; import fl.transitions.easing.Elastic; // sections var captions:Array = new Array ( "Homepage", "Photos", "Links", "Contact" ); // creation of a container var container:Sprite = new Sprite(); container.x = 20; addChild ( container ); function createMenu ():void { var lng:int = captions.length; var myButton:Button; for ( var i:int = 0; i< lng; i++ ) { // creation of instances of the button symbol myButton = new Button(); // variable referencing the clip used for the upState var upState:MovieClip = MovieClip ( myButton.upState ); upState.myCaption.text = captions[i]; // modification of clip for all states myButton.upState = upState; myButton.downState = upState myButton.overState = upState myButton.hitTestState = upState // arrangement of instances myButton.tween = new Tween ( myButton, "y", Elastic.easeOut, 0, 20 + i * (myButton.height + 10), 3, true ); // a Tween object is created for the rollover effects myButton.tweenRollover = new Tween ( myButton, "scaleX", Elastic.easeOut, 1, 1, 2, true ); container.addChild ( myButton ); } } createMenu(); // capture of the MouseEvent.CLICK event in the container container.addEventListener ( MouseEvent.CLICK, clickMenu, true ); container.addEventListener ( MouseEvent.ROLL_OVER, rolloverButton, true ); container.addEventListener ( MouseEvent.ROLL_OUT, rolloutButton, true ); function rolloverButton ( pEvt:MouseEvent ):void { var myTween:Tween = pEvt.target.tweenRollover; myTween.continueTo ( 1.1, 2 ); } function rolloutButton ( pEvt:MouseEvent ):void { var myTween:Tween = pEvt.target.tweenRollover; myTween.continueTo ( 1, 2 ); } function clickMenu ( pEvt:MouseEvent ):void { // displays : [object Button] trace( pEvt.target ); // displays : [object Sprite] trace( pEvt.currentTarget ); }
In the rolloverButton and rolloutButton functions we get the Tween object associated with the rollover object in the myTween variable. Thanks to the continueTo method of the Tween object, we can restart, stop or start the animation in the opposite direction. In the previous code we had defined the arrival and departure values of the extension of the Button. We increase the size of the Button by 10% on rollover and return the size of the Button to 100% when we leave the rollover state.
We get an elastic menu on rollover but there is one more thing to optimize. If we look carefully we can see that the text inside the Button is also resized. This problem happens as we resize the Button’s main container in which we find our textfield. In extending the container we extend the children and therefore the caption. We will modify our Button symbol in order to be able to resize the background shape of our Button without altering the textfield.
To do this, in the Button symbol we edit the clip placed on the upState and transform the background shape into a clip in which we give it the occurrence name backgroundButton. We will resize the internal clip in the upState without altering the textfield. We will modify our code by associating the Tween object with the backgroundButton clip:
// a Tween object is created for the rollover effects myButton.tweenRollover = new Tween ( upState.backgroundButton, "scaleX", Elastic.easeOut, 1, 1, 2, true );
In summary, the SimpleButton class proves to be very useful but makes our Buttons quite basic. Contrary to the Button class in ActionScript 1 and 2, the SimpleButton class can broadcast an Event.ENTER_FRAME event. The use of the SimpleButton class proves to be limiting in terms of visual interest.
We are going to redo the same exercise by using instances of Sprite this time, to which we will add a Button behavior.
Worth remembering
- The Tween class allows us to add movement to our graphic objects.
- This resides in the f1.transitions package and should be imported to be used.
- The different methods and properties of the Tween class allow us to manage movement.
Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42




