flash native_classes_dynamic_buttons

Creating dynamic buttons

We are going to extend the Sprite class in order to create dynamic buttons. These allow us to create a menu that can be modified at a later date in order to give life to this type of menu.

In the chapter entitled “Interactivity” we developed a menu made up of Sprite type buttons. All the behaviors were defined outside of it, we therefore needed to create the corresponding symbol, then in the loop add the button behaviors, the different rollover effects, then add the text. It was therefore impossible to quickly create an identical button in another application.

By using an object oriented approach with the help of a graphic sub-class we can define a Button class which can be reused in each application requiring a functional button.

We’re now going to organize our classes by placing them in specific packages. In the previous chapter we looked at packages without really using them. It is now the time to use this concept, this will allow us to organize our classes properly and to avoid conflicts between certain situations.

We start by creating a new Flash CS3 document next to which we create an org directory containing a bytearray directory. Then in this directory we create another directory called ui.

In the ui directory we create a sub-class of Sprite called Button containing the following code:

package org.bytearray.ui
{
import flash.display.Sprite;
public class Button extends Sprite
{
public function Button ()
{
trace ( this );
}
}
}

We can see that the package reflects the position of the class in the directory, if the path isn’t correct the compiler doesn’t find the class and generates an error. To instatiate the Button class in our Flash document we have to import it as the compiler looks for classes situated alongside to the .fla file by default but doesn’t browse all the neighbouring directorys in order to find the class definition.

We tell it where it is using the keyword import:

// importing the Button class
import org.bytearray.ui.Button;
// displays : [object Button]
var myButton:Button = new Button();

Our button is correctly created but for the moment it doesn’t give us much more that a direct creation of the Sprite class, we will now add some functionality. We will dynamically draw the button using the drawing API. Thanks to inheritance, the Button class has all the capabilities of a Sprite and therefore inherits a graphics property unique to the drawing API.

We could directly draw in the Button class but we prefer the use of a Shape object dedicated for this use. If we want to add a rollover effect at a later date we modify this in order to extend the main container of the button which evokes a global extension of all the button’s children.

We draw the button in the Button class’ constructor:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
public class Button extends Sprite
{
// references the background of the button
private var buttonBackground:Shape;
public function Button ()
{
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// draws the button
buttonBackground.graphics.beginFill ( Math.random()*0xFFFFFF, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
}
}
}

We choose a random colour, then we draw a rectangular shape, later on we can choose the colour of the button or its dimensions. We just now need to display it:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
// instancing
// displays : [object Button]
var myButton:Button = new Button();
// addition into the container
containerMenu.addChild ( myButton );
// display of buttons
addChild ( containerMenu );

9.9.1.jpg

In order to make our button clickable we have to activate a property. The buttonMode property allows us to do this in any DisplayObject:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
public function Button ()
{
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// draws the button
buttonBackground.graphics.beginFill ( Math.random()*0xFFFFFF, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
}
}
}

The hand cursor displays when we rollover the button:

9.9.2.jpg

We are going to add some movement to it by using the Tween class. We import it then create an object of the same type in order to manage the rollover:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
// importation of Tween classes linked to the movement
import fl.transitions.Tween;
import fl.transitions.easing.Bounce;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
// stores the Tween classes for the different button states
private var interpolation:Tween;
public function Button ()
{
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// draws the button
buttonBackground.graphics.beginFill ( Math.random()*0xFFFFFF, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// creation of the Tween object
interpolation = new Tween (buttonBackground, "scaleX", Bounce.easeOut,
1, 1, 1, true );
}
}
}

We ask the Tween object to look after the scaleX property to give an extension effect on the Shape object acting as our button background. We will then give it a bounce effect using the class bounce.

When we rollover the button we start the animation. We listen to the MouseEvent.ROLL_OVER event:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
// importation of Tween classes linked to the movement
import fl.transitions.Tween;
import fl.transitions.easing.Bounce;
// importation of the MouseEvent class
import flash.events.MouseEvent;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
// stores the Tween classes for the different button states
private var interpolation:Tween;
public function Button ()
{
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// draws the button
buttonBackground.graphics.beginFill ( Math.random()*0xFFFFFF, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut,
1, 1, 1, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}
// triggered on button rollover
private function rolloverMouse ( pEvt:MouseEvent ):void
{
// start of the animation
interpolation.continueTo ( 2, 2 );
}
}
}

On rollover the button extends with a bounce effect:

9.9.3.jpg

By adding other buttons we get a menu:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
var lng:int = 5;
var myButton:Button;
for (var i:int = 0; i< lng; i++ )
{
// instancing
// creation of red buttons
myButton = new Button();
// positioning
myButton.y = 50 * i;
// addition into the container
containerMenu.addChild ( myButton );
}
// display of buttons
addChild ( containerMenu );

The result is illustrated here:

9.9.4.jpg

The Button class can therefore be reused in any project just requiring one button or one menu.

We are still missing the functionality allowing us to close the clicked button when another is selected. To do this we have to have a reference to all of the buttons in the menu and then to decide which buttons to close.

In the chapter entitled “Object oriented programming” we discussed the player class. We also defined an array storing references to each player created which allowed us to know how many players had been created and to be able to access them at any time. We are going to reproduce the same mechanism using a static array.

The arrayButtons array stores each button reference:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
// importation of Tween classes linked to the movement
import fl.transitions.Tween;
import fl.transitions.easing.Bounce;
// importation of the MouseEvent class
import flash.events.MouseEvent;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
// stores the Tween classes for the different button states
private var interpolation:Tween;
// stores button references
private static var arrayButtons:Array = new Array();
public function Button ()
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// draws the button
buttonBackground.graphics.beginFill ( Math.random()*0xFFFFFF, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut,
1, 1, 1, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}
// triggered on button rollover
private function rolloverMouse ( pEvt:MouseEvent ):void
{
// start of the animation
interpolation.continueTo ( 2, 2 );
}
}
}

At any moment a button can browse the static array and access its siblings and decide to close them.

We modify the rolloverMouse method in order to call the close method on each button:

// triggered on button rollover
private function rolloverMouse ( pEvt:MouseEvent ):void
{
// stores the length of the array
var lng:int = Button.arrayButtons.length;
for (var i:int = 0; i<lng; i++ ) Button.arrayButtons[i].close();
// start of the animation
interpolation.continueTo ( 2, 1 );
}

The close method is private as this will only be called in the button class:

// method allowing the closure of the button
private function close ():void
{
// closes the button
interpolation.continueTo ( 1, 1 );
}

If we test the animation we can see that on rollover the open buttons close.

Of course in the majority of ActionScript projects we will not only want to create menus with random colours. It would be good to be able to choose the colour of each button, to do this we add a parameter in order to take the colour of the button in the constructor:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
// importation of Tween classes linked to the movement
import fl.transitions.Tween;
import fl.transitions.easing.Bounce;
// importation of the MouseEvent class
import flash.events.MouseEvent;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
// stores the Tween classes for the different button states
private var interpolation:Tween;
// stores button references
private static var arrayButtons:Array = new Array();
// stores the button colour in progress
private var colour:Number;
public function Button ( pColour:Number )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// stores the colour passed into parameter
colour = pColour;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut,
1, 1, 1, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}
// triggered on button rollover
private function rolloverMouse ( pEvt:MouseEvent ):void
{
// stores the length of the array
var lng:int = Button.arrayButtons.length;
for (var i:int = 0; i<lng; i++ )
Button.arrayButtons[i].close();
// start of the animation
interpolation.continueTo ( 2, 2 );
}
// method allowing the closure of the button
private function close ():void
{
// closes the button
interpolation.continueTo ( 1, 1 );
}
}
}

From now on the Button class accepts a colour parameter, the following code creates a menu with red buttons only:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
var lng:int = 5;
var myButton:Button;
for (var i:int = 0; i< lng; i++ )
{
// instancing
// creation of red buttons
myButton = new Button( 0x990000 );
// positioning
myButton.y = 50 * i;
// addition into the container
containerMenu.addChild ( myButton );
}
// display of buttons
addChild ( containerMenu );

This doesn’t have much use so we will modify the code in order to associate a precise colour to each button. To do this we store the colours in an array that will be browsed, the number of buttons in the menu is linked to the length of the array:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
// array of colours
var colours:Array = [0x999900, 0x881122, 0x995471, 0x332100, 0x977821];
// number of colours
var lng:int = colours.length;
var myButton:Button;
for (var i:int = 0; i< lng; i++ )
{
// instancing
// creation of red buttons
myButton = new Button( colours[i] );
// positioning
myButton.y = 50 * i;
// addition into the container
containerMenu.addChild ( myButton );
}
// display of buttons
addChild ( containerMenu );

We get the following menu:

9.9.5.jpg

Each button accepts a colour on its creation; we can imagine an application in which the user chooses the colour of menu buttons in a management system. The colours are therefore retrieved from a database then used to create the menu. We will see how to put this application into practice in the chapter entitled “Flash remoting”.

Our menu is not yet finished; it would be good to specify the opening speed of each button. We have already used this control for the pencil in the previous chapter. Our objects are of the same family but have different characteristics such as the colour or opening speed.

To do this we use the private speed property which looks after storing the speed given to each button:

// stores the opening speed of each button
private var speed:Number;

Then we define an allocateSpeed method which changes the speed in a controlled way:

// manages the allocation of speed
public function allocateSpeed ( pSpeed:Number ):void
{
// allocation of speed
if ( pSpeed >= 1 && pSpeed <= 10 ) speed = pSpeed;
else
{
trace("Error : Speed not correct, the value should be
between 1 and 10");
speed = 1;
}
}

We modify the constructor by adding a parameter called pFriction in order to call the allocateSpeed method before the creation of the Tween object to initialise the speed property:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
// importation of Tween classes linked to the movement
import fl.transitions.Tween;
import fl.transitions.easing.Bounce;
// importation of the MouseEvent class
import flash.events.MouseEvent;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
// stores the Tween classes for the different button states
private var interpolation:Tween;
// stores button references
private static var arrayButtons:Array = new Array();
// stores the button colour in progress
private var colour:Number;
// stores the opening speed of each button
private var speed:Number;
public function Button ( pColour:Number, pSpeed:Number=.1 )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// stores the colour passed into parameter
colour = pColour;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut, 1,
1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}
// triggered on button rollover
private function rolloverMouse ( pEvt:MouseEvent ):void
{
// stores the length of the array
var lng:int = Button.arrayButtons.length;
for (var i:int = 0; i<lng; i++ ) Button.arrayButtons[i].close();
// start of the animation
interpolation.continueTo ( 2, speed );
}
// method allowing the closure of the button
private function close ():void
{
// closes the button
interpolation.continueTo ( 1, speed );
}
// manages the allocation of speed
public function allocateSpeed ( pSpeed:Number ):void
{
// allocation of speed
if ( pSpeed >= 1 && pSpeed <= 10 ) speed = pSpeed;
else
{
trace("Error : Speed not correct, the value should be
between 1 and 10");
speed = 1;
}
}
}
}

In the following code, we create a menu comprising of buttons of which we can choose the opening speed:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
// array of colours
var colours:Array = [0x999900, 0x881122, 0x995471, 0x332100, 0x977821];
// number of colours
var lng:int = colours.length;
var myButton:Button;
for (var i:int = 0; i< lng; i++ )
{
// instancing
// creation of red buttons
myButton = new Button( colours[i], 1 );
// positioning
myButton.y = 50 * i;
// addition into the container
containerMenu.addChild ( myButton );
}
// display of menu
addChild ( containerMenu );

If the wrong speed has been given, the menu continues to work and an error message is displayed:

// displays : Error : Speed not correct, the value
// should be between 1 and 10
var myButton:Button = new Button( colours[i], 0 );

Generally buttons contain a caption, we will therefore add a textfield to each button. To do this we import the flash.text.TextField and flash.text.TextFieldAutoSize classes:

// importing the TextField and TextFieldAutoSize classes
import flash.text.TextField;
import flash.text.TextFieldAutoSize;

We create a caption property in order to reference the caption:

// button’s caption
private var caption:TextField;

Then we add the textfield to the button in the constructor:

public function Button ( pColour:Number, pSpeed:Number=.1 )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// creates the textfield
caption = new TextField();
// automatically resizes the textfield
caption.autoSize = TextFieldAutoSize.LEFT;
// makes the textfield unselectionable
caption.selectable = false;
// addition to the display list
addChild ( caption );
// stores the colour passed into parameter
colour = pColour;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut, 1,
1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}

If we test our menu we see that the textfield overlaid in the button receives mouse actions and enters into conflict with the main container of the button.

In order to deactivate the child objects of the button we pass the false property to the mouseChildren property of the button:

// deactivation of child objects
mouseChildren = false;

Remember in the chapter entitled Interactivity we saw that the mouseChildren property allowed us to deactivate the mouse events in child objects.

We add a parameter to the constructor of the Button class in order to accept the text displayed by the caption:

public function Button ( pColour:Number, pSpeed:Number=.1,
pCaption:String="Caption" )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// creates the textfield
caption = new TextField();
// automatically resizes the textfield
caption.autoSize = TextFieldAutoSize.LEFT;
// makes the textfield unselectionable
caption.selectable = false;
// addition to the display list
addChild ( caption );
// allocates the caption
caption.text = pCaption;
// stores the colour passed into parameter
colour = pColour;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// deactivation of child objects
mouseChildren = false;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut, 1,
1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}

The data used to generate a menu generally come from an XML feed or Flash Remoting and are very often formatted in the form of the associative array.

We are going to reorganize the data in order to use an associative array rather than multiple separated arrays:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
// associative array containing data
var data:Array = new Array();
data.push ( { caption : "Homepage", speed : 1, colour : 0x999900 } );
data.push ( { caption : "Photos", speed : 1, colour : 0x881122 } );
data.push ( { caption : "Blog", speed : 1, colour : 0x995471 } );
data.push ( { caption : "Links", speed : 1, colour : 0x332100 } );
data.push ( { caption : "Forum", speed : 1, colour : 0x977821 } );
// number of sections
var lng:int = data.length;
var myButton:Button;
var caption:String;
var colour:Number;
var speed:Number;
for (var i:int = 0; i< lng; i++ )
{
// recuperation of information
caption = data[i].caption;
colour = data[i].colour;
speed = data[i].speed;
// creation of buttons
myButton = new Button( colour, speed, caption );
// positioning
myButton.y = 50 * i;
// addition into the container
containerMenu.addChild ( myButton );
}
// display of menu
addChild ( containerMenu );

By testing our menu we get the following result:

9.9.6.jpg

The caption text is not correctly formatted, to remedy this we use the flash.text.TextFormat class as well as the flash.text.Font class. We will go into this in more detail in the chapter entitled “Text”.

To integrate a font in the library we click on the top right icon as illustrated here:

9.9.7.jpg

The library options panel opens and we select New font as illustrated here:

9.9.8.jpg

Once selected, the Font symbol properties panel is displayed which allows you to select the font that will be used in the animation. We select Trebuchet MS as our font in this example then we give a class name to the font and save it as Font 1.

9.9.9.jpg

Once validated, the font appears in the library, we just need to use it in the textfields contained in each button. To do this we have to link this font like a classic symbol. By right clicking on it we select the Linking option in the Linking properties panel opens:

9.9.10.jpg

We choose the class name myFont, this will automatically be created by Flash and will be inherited from the flash.text.Font class.

We define a new formatting property in order to store the TextFormat object:

// formatting captions
private var formatting:TextFormat;

We import the flash.text.TextFormat class:

import flash.text.TextFormat;

Then we modify the constructor of the Button class in order to allocate the formatting and to indicate to the textfield to use the chosen font:

public function Button ( pColour:Number, pSpeed:Number, pCaption:String
)
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// creates the textfield
caption = new TextField();
// automatically resizes the textfield
caption.autoSize = TextFieldAutoSize.LEFT;
// addition to the display list
addChild ( caption );
// allocates the caption
caption.text = pCaption;
// activates the use of the chosen font
caption.embedFonts = true;
// creates a formatting object
formatting = new TextFormat();
// size of the font
formatting.size = 12;
// instancing of the chosen font
var Font:MyFont = new MyFont();
// allocation of the font to the formatting
formatting.font = Font.fontName;
// allocation of formatting to the textfield
caption.setTextFormat ( formatting );
// makes the text unselectionnable
caption.selectable = false;
// stores the colour passed into parameter
colour = pColour;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, 40, 110 );
// activation of button mode
buttonMode = true;
// deactivation of child objects
mouseChildren = false;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut, 1,
1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}

When testing the previous code, each button has a caption integrating the contours of the font:

9.9.11.jpg

All that remains for us to do to integrate a management of the height and width on each button. To do this we add two parameters pWidth and pHeight to the constructor of the button class:

public function Button ( pWidth:Number, pHeight:Number, pColour:Number,
pSpeed:Number, pCaption:String )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// creates the textfield
caption = new TextField();
// automatically resizes the textfield
caption.autoSize = TextFieldAutoSize.LEFT;
// addition to the display list
addChild ( caption );
// allocates the caption
caption.text = pCaption;
// activates the use of the chosen font
caption.embedFonts = true;
// creates a formatting object
formatting = new TextFormat();
// size of the font
formatting.size = 12;
// instancing of the chosen font
var Font:MyFont = new MyFont();
// allocation of the font to the formatting
formatting.font = Font.fontName;
// allocation of formatting to the textfield
caption.setTextFormat ( formatting );
// makes the text unselectionnable
caption.selectable = false;
// stores the colour passed into parameter
colour = pColour;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, pWidth, pHeight );
// activation of button mode
buttonMode = true;
// deactivation of child objects
mouseChildren = false;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut, 1,
1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}

Then we pass the desired values on creation of each button:

// creation of buttons
myButton = new Button( 60, 120, colour, speed, caption );

Here is the final result:

9.9.12.jpg

We get a simple menu which is easily modifiable. We can add other functionalities such as automatic adaptation of the width of a button in relation to the caption. We can go as far as we like!

In many projects, the buttons of a menu are generally linked to SWFs. When the button is clicked the corresponding SWF is loaded, this allows a better organization of the site and loading on demand. We are going to modify the button class in order to be able to store the name of the corresponding SWF to each button.

We add a swf property:

// swf associated
private var swf:String;

Then we modify the constructor in order to get the name of the associated SWF:

public function Button ( pWidth:Number, pHeight:Number, pSWF:String,
pColour:Number, pSpeed:Number, pCaption:String )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// creates the textfield
caption = new TextField();
// automatically resizes the textfield
caption.autoSize = TextFieldAutoSize.LEFT;
// addition to the display list
addChild ( caption );
// allocates the caption
caption.text = pCaption;
// activates the use of the chosen font
caption.embedFonts = true;
// creates a formatting object
formatting = new TextFormat();
// size of the font
formatting.size = 12;
// instancing of the chosen font
var Font:MyFont = new MyFont();
// allocation of the font to the formatting
formatting.font = Font.fontName;
// allocation of formatting to the textfield
caption.setTextFormat ( formatting );
// makes the text unselectionnable
caption.selectable = false;
// stores the colour passed into parameter
colour = pColour;
// stores the name of the associated swf
swf = pSWF;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, pWidth, pHeight );
// activation of button mode
buttonMode = true;
// deactivation of child objects
mouseChildren = false;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut, 1,
1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}

Then we instantiate the menu buttons:

// importing the Button class
import org.bytearray.ui.Button;
// creation of the container for the menu
var containerMenu:Sprite = new Sprite();
// associative array containing data
var data:Array = new Array();
data.push ( { caption : "Homepage", speed : 1, swf : "homepage.swf",
colour : 0x999900 } );
data.push ( { caption : "Photos", speed : 1, swf : "photos.swf", colour
: 0x881122 } );
data.push ( { caption : "Blog", speed : 1, swf : "blog.swf", colour :
0x995471 } );
data.push ( { caption : "Links", speed : 1, swf : "links.swf", colour :
0xCC21FF } );
data.push ( { caption : "Forum", speed : 1, swf : "forum.swf", colour :
0x977821 } );
// number of sections
var lng:int = data.length;
var myButton:Button;
var caption:String;
var colour:Number;
var speed:Number;
var swf:String;
for (var i:int = 0; i< lng; i++ )
{
// recuperation of information
caption = data[i].caption;
colour = data[i].colour;
speed = data[i].speed;
swf = data[i].swf;
// creation of buttons
myButton = new Button( 60, 120, swf, colour, speed, caption );
// positioning
myButton.y = 50 * i;
// addition into the container
containerMenu.addChild ( myButton );
}
// display of menu
addChild ( containerMenu );

Each button is linked to a SWF. In the chapter entitled “Interactivity” we created a dynamic menu which sends us to a specific address by opening a new browser window. To do this we store the link in the property of a button, then when it’s clicked we access the SWF.

Here is the final code of the Button class:

package org.bytearray.ui
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.text.Font;
import flash.text.TextFormat;
// importation of classes linking Tween to the movement
import fl.transitions.Tween;
import fl.transitions.easing.Bounce;
// importation of the MouseEvent class
import flash.events.MouseEvent;
// importing the TextField and TextFieldAutoSize classes
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
public class Button extends Sprite
{
// stores the button background
private var buttonBackground:Shape;
// stores the Tween classes for the different button states
private var interpolation:Tween;
// stores button references
private static var arrayButtons:Array = new Array();
// stores the button colour in progress
private var colour:Number;
// stores the opening speed of each button
private var speed:Number;
// button’s caption
private var caption:TextField;
// formatting captions
private var formatting:TextFormat;
// swf associated
private var swf:String;
public function Button ( pWidth:Number, pHeight:Number,
pSWF:String, pColour:Number, pSpeed:Number, pCaption:String )
{
// adds each instance to the array
Button.arrayButtons.push ( this );
// creation of the button background
buttonBackground = new Shape();
// addition to the display list
addChild ( buttonBackground );
// creates the textfield
caption = new TextField();
// automatically resizes the textfield
caption.autoSize = TextFieldAutoSize.LEFT;
// addition to the display list
addChild ( caption );
// allocates the caption
caption.text = pCaption;
// activates the use of the chosen font
caption.embedFonts = true;
// creates a formatting object
formatting = new TextFormat();
// size of the font
formatting.size = 12;
// instancing of the chosen font
var Font:MyFont = new MyFont();
// allocation of the font to the formatting
formatting.font = Font.fontName;
// allocation of formatting to the textfield
caption.setTextFormat ( formatting );
// makes the text unselectionnable
caption.selectable = false;
// stores the colour passed into parameter
colour = pColour;
// stores the name of the SWF
swf = pSWF;
// draws the button
buttonBackground.graphics.beginFill ( colour, 1 );
buttonBackground.graphics.drawRect ( 0, 0, pWidth, pHeight );
// activation of button mode
buttonMode = true;
// deactivation of child objects
mouseChildren = false;
// allocation of the speed controlled
allocateSpeed ( pSpeed );
// creation of the Tween object
interpolation = new Tween ( buttonBackground, "scaleX", Bounce.easeOut,
1, 1, speed, true );
// listens to the MouseEvent.CLICK event
addEventListener ( MouseEvent.ROLL_OVER, rolloverMouse );
}
// triggered on button rollover
private function rolloverMouse ( pEvt:MouseEvent ):void
{
// stores the length of the array
var lng:int = Button.arrayButtons.length;
for (var i:int = 0; i<lng; i++ )
Button.arrayButtons[i].close();
// start of the animation
interpolation.continueTo ( 2, speed );
}
// method allowing the closure of the button
private function close ():void
{
// closes the button
interpolation.continueTo ( 1, speed );
}
// manages the allocation of speed
public function allocateSpeed ( pSpeed:Number ):void
{
// allocation of speed
if ( pSpeed >= 1 && pSpeed <= 10 ) speed = pSpeed;
else
{
trace("Error : Speed not correct, the value should be
between 1 and 10");
speed = 1;
}
}
}
}

This approach works perfectly and is suitable for many situations. When we use the personalized classes as in this application we externalize the necessary information thanks to the event model. In this way the objects “speak” to each other in a weakly coupled way.

We are going to use the same model as the ActionScript 3 native objects, each button could broadcast a specific event informing us on its colour, speed and the corresponding SWF.

Some of you will have guessed where we are heading next. Onwards for “Personalised event broadcasts”.








Adobe Training center


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