Actionscript 3.0 Xml driven menu.

We will build a menu witch is powered by an xml file; this offers a lot of flexibility because you can add/remove buttons by modifying the xml file and not by modifying the .fla file. The buttons will maintain they down state when clicked. We will not have any code on the timeline, all the code will reside in external classes, so it’s not only an xml driven menu it’s also coded in OOP style. We will use something called optional parameters; they are parameters that have a default value. To better understand this, let look at a simple example.

function sayMyName(name:String = "Sorin"):void {
trace (name);
}
//We have a function with a parameter called name witch has a default value(Sorin),
//if we call the function with no parameter passed to it the output will be Sorin sayMyName(); output: Sorin
//if we call the function with a custom value("Elvis") the function will output Elvis sayMyName("Elvis"); output: Elvis

Here is how the menu looks with the default arguments: xml menu with default arguments And the menu with custom arguments: xml menu with custom arguments

1. Establish the project structure.

Make the same folder hierarchy like in the image. menu folder hierarchy -gs contain the TweenLite api, a tweening engine that we will be using in our project. Download it from http://blog.greensock.com/tweenliteas3/ and place the gs folder inside the XML_menu folder(it will not be included in the source files);
-ro\Sorin\utils\ will hold our classes
The other folders are self-explanatory. We have a swf folder because our menu has to do something, in this case it will load some external swfs.

2. Creating the xml file structure.

The xml file looks like this:

<?xml version="1.0" encoding="utf-8"?>
<menu>
<item>
<label>Home</label>
<url><![CDATA[swf/home.swf]]></url>
</item>
<item>
<label>About</label>
<url><![CDATA[swf/about.swf]]></url>
</item>
<item>
<label>Portofolio</label>
<url><![CDATA[swf/portofolio.swf]]></url>
</item>
<item>
<label>Contact</label>
<url><![CDATA[swf/contact.swf]]></url>
</item>
</menu>
Every item tag contains the data for one button. Make an identical xml file and save it as menu.xml in the xml folder.

3. Creating the swf files.

We will have 4 buttons so we need 4 swfs. Create 4 swfs with the width: 435 and height: 245 Save them in the swf folder with the fallowing names: home.swf, about.swf, portofolio.swf and contact.swf. Put anything you want on this swfs, just make them different so we can know that we have loaded a different swf. Mine looks like this: home page swf

4. The CustomButon class.

I will not explain every line of code, if there are portions of code that you don’t understand just ask and I will try to explain it. I have tried to give to the variables and functions meaningful names.I hope that this will make code understanding easier. For example: btnBg means button background btnId - the buttons id; overColor – the color that you see when the mouse it’s over the button

package ro.Sorin.utils {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
import gs.TweenLite;
/**
* ...
* @author ...Sorin Haidan
http://biochimistu.blogspot.com */
public class CustomButton extends MovieClip{
private var btnBg:Sprite;
private var btnTextField:TextField;
private var btnText:String;
private var btnTextFormat:TextFormat;
private var btnWidth:Number;
private var btnHeight:Number;
private var outColor:uint;
private var overColor:uint;
private var textColor:uint;
private var btnId:uint;
public function CustomButton(_btnText:String, _btnWidth:Number=150, _btnHeight:Number=60){
btnWidth = _btnWidth;
btnHeight = _btnHeight;
btnText = _btnText;
setButtonsColor();
}
public function setButtonsColor(_outColor:uint= 0x376032, _overColor:uint = 0x141140, _textColor:uint=0xF8ECC2):void{
outColor = _outColor;
overColor = _overColor;
textColor = _textColor;
init();
}
private function init():void{
btnBg = new Sprite();
btnBg.graphics.lineStyle(0, 0, 0);
btnBg.graphics.beginFill(outColor, 1);
btnBg.graphics.drawRect(0, 0, btnWidth, btnHeight);
btnBg.graphics.endFill();
addChild(btnBg);
btnTextFormat = new TextFormat();
btnTextFormat.align = TextFormatAlign.CENTER;
btnTextFormat.size = 16;
btnTextFormat.bold = true;
btnTextField = new TextField();
btnTextField.width = btnBg.width;
btnTextField.selectable = false;
btnTextField.wordWrap = true;
btnTextField.multiline = false;
btnTextField.textColor = textColor;
btnTextField.autoSize = TextFieldAutoSize.CENTER;
btnTextField.defaultTextFormat = btnTextFormat;
btnTextField.text = btnText;
btnTextField.y = btnBg.height / 2 - btnTextField.height / 2;
addChild(btnTextField);
}
public function doOver():void{
TweenLite.to(btnBg, 0.5, { tint:overColor } );
}
public function doOut():void{
TweenLite.to(btnBg, 0.5, { tint:outColor } );
}
public function get id():uint{
return btnId;
}
public function set id(_id:uint):void{
btnId = _id;
}
}
}

The CustomButton function is the constructor class (this function is called when we create a new button object) it has 3 parameters but only one is required (_btnText:String) the other two are optional parameters, they have a default value(_btnWidth:Number=150, _btnHeight:Number=60). So we can create a new button by passing only one argument var testBtn:CustonButton = new CustomButton("Home"); this button will have 150 pixels for the width and 60 for the height or if we want a button with different size we can do like this: var testBtn:CustonButton = new CustomButton("Home", 120, 45); this button will have 120 pixels for the width and 45 for the height.
The setButtonsColor function handles the button colors. It has 3 parameters with default values, if you don’t like the default colors you can call this function with your custom colors.
Inside the init function we draw the button, format and align the text. Copy the code in a new as3 and save it as CustomButton.as in the utils folder.

5. The Main class.

This will be our Document class, the entry point to our project.

package{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.MouseEvent;
import ro.Sorin.utils.*;
import gs.TweenLite;
/**
* ...
* @author ...Sorin Haidan
http://biochimistu.blogspot.com
*/
public class Main extends MovieClip{
private var testBtn:CustomButton;
private var loadXML:TextLoader;
private var xmlMenu:XML;
private var xmlList:XMLList;
private var nrOfBtn:uint;
//-----contains the custom buttons as objects
private var btnArray:Array = new Array();
//-----contains the paths to the swfs
private var urlArray:Array = new Array();
private var menu:Sprite = new Sprite();
//-----the parent of the swfs
private var pageContainer:MovieClip = new MovieClip();
private var loader:Loader = new Loader();
private var urlRequest:URLRequest;
public function Main(){
loadXML = new TextLoader("xml/menu.xml");
loadXML.addEventListener(Event.COMPLETE, xmlLoaded);
menu.x = menu.y = 5;
addChild(menu);
pageContainer.x = 160;
pageContainer. y = 5;
addChild(pageContainer);
}
private function xmlLoaded(event:Event):void{
xmlMenu = XML(event.target.content);
xmlList = xmlMenu.children();
nrOfBtn = xmlList.length();
makeButtons();
}
private function makeButtons():void{
for (var i:uint = 0; i < nrOfBtn; i++) { testBtn = new CustomButton(xmlList[i].label); //testBtn.setButtonsColor(0x804D2E, 0x522015, 0xffffff); testBtn.y = i * (testBtn.height +2); menu.addChild(testBtn); btnArray.push(testBtn); urlArray.push(xmlList[i].url); } addBtnBehavior(); } private function addBtnBehavior():void { for (var j:uint = 0; j < btnArray.length; j++) { btnArray[j].id = j; btnArray[j].buttonMode = true; btnArray[j].mouseChildren = false; btnArray[j].mouseEnabled = true; btnArray[j].addEventListener(MouseEvent.MOUSE_OVER,handleOver); btnArray[j].addEventListener(MouseEvent.MOUSE_OUT,handleOut); btnArray[j].addEventListener(MouseEvent.CLICK,doClick); } //-----first button will be selected setSelectedBtn(0); } private function handleOver(event:MouseEvent):void { event.target.doOver(); } private function handleOut(event:MouseEvent):void { event.target.doOut(); } private function doClick(event:MouseEvent):void { setSelectedBtn(event.currentTarget.id); } private function setSelectedBtn(_id:uint):void { for (var k:uint = 0; k < btnArray.length; k++) { if (_id == k) { btnArray[k].doOver(); loadContent(_id); btnArray[k].buttonMode = false; btnArray[k].mouseEnabled = false; btnArray[k].removeEventListener(MouseEvent.MOUSE_OVER,handleOver); btnArray[k].removeEventListener(MouseEvent.MOUSE_OUT,handleOut); btnArray[k].removeEventListener(MouseEvent.CLICK,doClick); } else { btnArray[k].doOut(); btnArray[k].buttonMode = true; btnArray[k].mouseEnabled = true; btnArray[k].addEventListener(MouseEvent.MOUSE_OVER,handleOver); btnArray[k].addEventListener(MouseEvent.MOUSE_OUT,handleOut); btnArray[k].addEventListener(MouseEvent.CLICK,doClick); } } } private function loadContent(_id:int):void { urlRequest = new URLRequest(urlArray[_id]); loader.unload(); loader.alpha = 0; loader.load(urlRequest); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,addSWF); } private function addSWF(event:Event):void { pageContainer.addChild(loader); TweenLite.to(loader, 1, {alpha:1}); } } }

We load the xml file by using a custom class that I have made (TextLoader), you will find this class in the utils folder.
First pass it the path to the xml file loadXML = new TextLoader("xml/menu.xml"); and then listen for a COMPLETE event loadXML.addEventListener(Event.COMPLETE, xmlLoaded);
When the COMPLTE event is dispatched we retrieve the loaded data, cast it as XML and assign it to an xml object. xmlMenu = XML(event.target.content);
Inside the makeButtons function we can change the appearance of the buttons. By uncommenting this line //testBtn.setButtonsColor(0x804D2E, 0x522015, 0xffffff); the over, out and text colors change. Give it a try, don’t forget to save the file. Copy the code in a new as3 file and save it as Main.as in the main folder(XML_menu).

6. Testing the application.

Create a new Flash file (Actionscript3).Set the stage dimensions to 600X255, frame rate to 30 and the Documents class to Main. Save the file as xml_menu.fla in the main folder (XML_menu).Press Ctrl + Enter to test it. You should have something similar to the image, a basic structure for a site; you can expand it and transform it in a complete flash site.

I hope that you enjoyed the tutorial. If you have questions, suggestions, doubts about the tutorial don’t hesitate to comment.Until next time have fun learning Flash.

Download the source files for here:Actionscript 3.0 Xml driven menu.

2 comentarii:

Post a Comment

  • Anonymous : July 5, 2009 at 6:18 AM

    Nice work.
    Only one thing. The url in the xml is wrong swf\ should be swf/.

  • Biochimistu : July 6, 2009 at 12:09 AM

    Sorry about that, my mistake. Thank you.