PDA

View Full Version : Flash AS 3.0 OO gallery - best practices


Flash Gordon
07-02-2007, 06:44 AM
Hi,

Attached are the files for a simple slideshow/gallery presentation. I'm looking for comments for best practice in OO or convention in AS 3.0. I understand I'm not checking for loading of images in such, as that isn't my focus right now.

Also, is it better to have callbacks like I'm doing from the classes and then make new classes as needed? Or is there a better way OO way of organizing the application?

Thanks
:)



scripts:

FLA

stop();
import com.flash9.xml.*;
import com.flash9.load.*;
import com.flash9.engines.*;


// references to classes
var slideshow:SlideShow;


//load xml
var info:ImagesXML = new ImagesXML();
info.addEventListener(Event.COMPLETE, onXML);
info.load("banner.xml");

function onXML(event:Event):void
{
// add text
company_txt.text = info.company;
industry_txt.text = info.industry;
url_txt.text = info.url;

// load images
for (var i:uint=0; i<info.images.length(); i++)
{
this["image"+i] = new LoadImage(container);
this["image"+i].load( info.images[i] );
}
container.setChildIndex(this["image0"], container.numChildren-1);

// start slide show
slideshow = new SlideShow(container);
slideshow.start();
}


ImagesXML

package com.flash9.xml
{

import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.EventDispatcher;

public class ImagesXML extends EventDispatcher
{
protected var loader:URLLoader;
protected var xml:XML;


public function ImagesXML()
{
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.TEXT;
loader.addEventListener(Event.COMPLETE, onLoad);
}

public function load(file:String):void
{
loader.load( new URLRequest(file) );
}

protected function onLoad(event:Event):void
{
xml = XML(loader.data);
dispatchEvent( new Event(Event.COMPLETE) );
}

public function get time():Number { return parseFloat(xml.@time) }
public function get company():String { return xml.set.client; }
public function get industry():String { return xml.set.industry; }
public function get url():String { return xml.set.url; }
public function get link():String { return xml.set.url.@link; }
public function get images():XMLList { return xml.pictures.image; }
}
}


LoadImage

package com.flash9.load
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
import flash.display.Sprite;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;

public class LoadImage extends Sprite
{
protected var _loader:Loader;
protected var _info:LoaderInfo;

public function LoadImage(target:DisplayObjectContainer=null)
{
_loader = new Loader();
addChild(_loader);

_info = LoaderInfo(_loader.contentLoaderInfo);
_info.addEventListener(Event.COMPLETE, onLoadInit);

if (target != null) target.addChild(this);
}

public function load(file:String):void
{
_loader.load( new URLRequest(file) );
}

protected function onLoadInit(event:Event):void
{
dispatchEvent( new Event(Event.COMPLETE) );
}
}
}

SlideShow

package com.flash9.engines
{

import fl.transitions.Tween;
import fl.transitions.easing.*;
import flash.display.DisplayObjectContainer;
import flash.utils.Timer;
import flash.events.TimerEvent;

public class SlideShow
{
protected var container:DisplayObjectContainer;
protected var delay:Number;
protected var clips:Array;
protected var nowShowing:uint = 0;

protected var timer:Timer;
protected var tween:Tween;

public function SlideShow(container:DisplayObjectContainer, delay:Number=3000)
{
this.container = container;
this.delay = delay;

clips = findChildren(container);

timer = new Timer(delay);
timer.addEventListener(TimerEvent.TIMER, toLoop);
}

private function findChildren(container:DisplayObjectContainer):Arr ay
{
var temp:Array = new Array();
for (var i:uint=0; i<container.numChildren; i++)
temp.push( container.getChildAt(i) );

return temp;
}

public function start():void
{
timer.start();
}

protected function toLoop(event:TimerEvent):void
{
container.setChildIndex(clips[nowShowing], container.numChildren-1);
tween = new Tween(clips[nowShowing], "alpha", None.easeNone, 0, 1, 1.0, true);

nowShowing = ++nowShowing % clips.length;
}
}
}


XML

<?xml version="1.0" encoding="iso-8859-1"?>
<banner time="5.5">

<set>
<client>Client Name: Google</client>
<industry>Expertise: Searching</industry>
<url link="http://www.google.com">www.google.com</url>
</set>

<pictures>
<image>image1.jpg</image>
<image>image2.jpg</image>
<image>image3.jpg</image>
<image>image4.jpg</image>
</pictures>

</banner>

panel
07-03-2007, 11:34 AM
I am not saying that my way is better or something. Just few minor advices.

1. I am naming class variables starting with underscore becouse when you are passing variable to method you don;t have to use this keyword.

this.container = container; //your way
_container = container; //my way


2. When parsing xml I am using try, catch. It's easy way to deal with incorrect xml especially when you edit it xml manually there is chance to make mistake.

function onXML(evt:Event)
{
try
{
_xml= new XML(evt.target.data);
processXML();
}
catch ( evt:TypeError )
{
trace("Could not parse text into XML");
trace(evt.message);
}
}


I would also split xml. Create one for images and one for 'banner info'.
Becouse in future you may add some parameters to image (title, navigateUrl) xml won't be so easy to read (in my opinion using one xml file for 2 things isn't good practice )

<Image>
<Title>Eye</Title>
<Url>Image3.png</Url>
<NavigateUrl>http://www.actionscript.org</NavigateUrl>
</Image>

3. In my photo gallery I am using two classes PhotoList and Photo.
This way I can create new photo object in PhotoList and manage add/remove to display list them when needed or Imagine situation when you have separate link for eqach photo. You could easly get current photo link.
Remember that processXML function runt from try block onXML, so if something is wrong with xml you will know.


private function processXML():void
{
for each (var property:XML in _xml.Photo)
{
var photo:Photo = new Photo(property.Title, property.ImageUrl, property.NavigateUrl);
photo.addEventListener("imageLoadComplete", onImageLoad);
_photos.push(photo); //now all photos are in array if you will remember currentPhotoIndex you could easly get to this photo properties
}
}


4. Consider using document class

Flash Gordon
07-10-2007, 12:22 AM
cool thanks bro!

It appear private/protected vars in a class begin with underscore so yea that is a good idea. and I used a doc class in my most recenty project.

Cheers
:)