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 );
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:
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:
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:
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:
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:
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:
The library options panel opens and we select New font as illustrated here:
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.
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:
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:
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:
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”.
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














