XML Horizontal Accordion Photos Gallery

In this AS3 tutorial, learn how to create an XML driven Horizontal Accordion that displays a list of Photos.

View DemoDownload Source

1. Create a new flash file (Actionscript 3.0) and save it as accordion.fla.

2. Create an XML file to store the photos’ datas and save it as datas.xml.

<photos>
	<photo>1.jpg</photo>
	<photo>2.jpg</photo>		
	<photo>3.jpg</photo>
	<photo>4.jpg</photo>
	<photo>5.jpg</photo>
</photos>

(Photos credits :Sunset, Seabirds In Flight, Apple Tree, Daffodils, White Cloud And Blue Sky)

3. Create an “actions” layer. Open the actions panel. We’ll use the Tweenlite engine so first write the following statements in order to use it and its easing properties.

import com.greensock.TweenLite;
import com.greensock.easing.*;

4. Next declare the following variables.

var xml:XML;
var folder ="photos/";
var totalPhotos:Number;
var photos:Array = new Array();
var photosLoaded:int = 0;
var current:Number = -1;
var accordion:Sprite
var photoWidth:uint;
var barWidth:Number;

5. Load the XML file :

function loadXML( file:String ):void{
	var xmlLoader:URLLoader = new URLLoader();
	xmlLoader.load(new URLRequest(file));
	xmlLoader.addEventListener(Event.COMPLETE,parseXML);
}

6. Then parse the XML :

function parseXML(e:Event):void {	
	xml = new XML( e.target.data );
	totalPhotos =xml.photo.length();	
	loadPhotos();
}

7. Inside the loadPhotos() function, we loop through the xml datas to create a Loader for each photo. The onComplete() function checks whether all photos are loaded. If so, it calls the createPanels() function.

function loadPhotos():void{
	for(var i:int = 0; i<totalPhotos; i++){
		var loader:Loader = new Loader();
		loader.load(new URLRequest(folder+ xml.photo[i]));
		photos.push(loader);
		loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
	}
}

function onComplete(e:Event):void{
	photosLoaded++;
	if(photosLoaded == totalPhotos)
		createPanels();
}

8. Inside the createPanels() function, loop through the photos array in order to create the accordion’s panels that contain the photos. Position each panel according to the stage’s width divided by the total number of photos.

function createPanels():void{	
	accordion = new Sprite();
	addChild(accordion);
	
	for(var i:int = 0; i < photos.length; i++){
	
		var panel:Sprite = new Sprite();
		barWidth = Math.ceil( stage.stageWidth / totalPhotos );
		panel.x = i  * barWidth;
		
		var bm:Bitmap = new Bitmap();
		bm = Bitmap(photos[i].content);
		bm.smoothing = true;
		panel.addChild(bm);
		accordion.addChild(panel);
		
		if (i==0) photoWidth=panel.width;

		if (i==photos.length-1)
			addListeners();		
	}
}

9. Once all the panels are created, we add our event listeners:

function addListeners():void{
	for( var i:int = 0; i < accordion.numChildren; i++ ){
		var sp:Sprite = accordion.getChildAt(i) as Sprite;
		sp.addEventListener(MouseEvent.ROLL_OVER, onPanelOver);
	}
	accordion.addEventListener(MouseEvent.ROLL_OUT,closePanels);
}

10. Inside the onPanelOver() function we set each panel x coordinate so that the current one is entirely visible.

function onPanelOver(e:MouseEvent):void{	
	var panel:Sprite = Sprite(e.target);
	current = accordion.getChildIndex(panel);
		
	barWidth = Math.ceil((stage.stageWidth-photoWidth) / (totalPhotos-1));
	
	for( var i :int = 0; i <accordion.numChildren; i++ ){		
		var sp:Sprite = Sprite(accordion.getChildAt(i));
		var newX:Number;
		
		if( i <= current )
			newX = i * barWidth;
		else
			newX = photoWidth + ( i - 1 ) * barWidth;
		
		TweenLite.to( sp, 1,{ x: newX,ease:Expo.easeOut} );
	}
}

11. Inside the closePanels() function, we reposition each panel so that their visible part are of the same size.

function closePanels(e:MouseEvent):void{
	var sp:Sprite;
	barWidth = Math.ceil(stage.stageWidth/totalPhotos);
	for( var i:int = 0; i < accordion.numChildren; i++ ){
		sp = Sprite(accordion.getChildAt(i) );
		TweenLite.to( sp, .5, { x: i * barWidth } );
	}
}

12. Finally don’t forget to call the loadXML() function to make it work.
Here’s the final code.

import com.greensock.TweenLite;
import com.greensock.easing.*;

var xml:XML;
var folder ="photos/";
var totalPhotos:Number;
var photos:Array = new Array();
var photosLoaded:int = 0;
var current:Number = -1;
var accordion:Sprite
var photoWidth:uint;
var barWidth:Number;

loadXML( "datas.xml" );

function loadXML( file:String ):void{
	var xmlLoader:URLLoader = new URLLoader();
	xmlLoader.load(new URLRequest(file));
	xmlLoader.addEventListener(Event.COMPLETE,parseXML);
}

function parseXML(e:Event):void {	
	xml = new XML( e.target.data );
	totalPhotos =xml.photo.length();	
	loadPhotos();
}

function loadPhotos():void{
	for(var i:int = 0; i<totalPhotos; i++){
		var loader:Loader = new Loader();
		loader.load(new URLRequest(folder+ xml.photo[i]));
		photos.push(loader);
		loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete);
	}
}

function onComplete(e:Event):void{
	photosLoaded++;
	if(photosLoaded == totalPhotos)
		createPanels();
}

function createPanels():void{	
	accordion = new Sprite();
	addChild(accordion);
	
	for(var i:int = 0; i < photos.length; i++){
	
		var panel:Sprite = new Sprite();
		barWidth = Math.ceil(stage.stageWidth/totalPhotos);
		panel.x = i  * barWidth;
		
		var bm:Bitmap = new Bitmap();
		bm = Bitmap(photos[i].content);
		bm.smoothing = true;
		panel.addChild(bm);
		accordion.addChild(panel);
		
		if (i==0) photoWidth=panel.width;

		if (i==photos.length-1)
			addListeners();		
	}
}
	
function addListeners():void{
	for(var i:int = 0; i < accordion.numChildren; i++){
		var sp:Sprite = accordion.getChildAt(i) as Sprite;
		sp.addEventListener(MouseEvent.ROLL_OVER, onPanelOver);
	}
	accordion.addEventListener(MouseEvent.ROLL_OUT,closePanels);
}

function onPanelOver(e:MouseEvent):void{	
	var panel:Sprite = Sprite(e.target);
	current = accordion.getChildIndex(panel);
		
	barWidth = Math.ceil((stage.stageWidth - photoWidth) / (totalPhotos-1));
	
	for(var i :int = 0; i <accordion.numChildren; i++){		
		var sp:Sprite = Sprite(accordion.getChildAt(i));
		var newX:Number;
		
		if(i <= current)
			newX = i * barWidth;
		else
			newX = photoWidth + (i-1) * barWidth;
		
		TweenLite.to(sp,1,{x: newX,ease:Expo.easeOut});
	}
}

function closePanels(e:MouseEvent):void{
	var sp:Sprite;
	barWidth = Math.ceil( stage.stageWidth / totalPhotos );
	for(var i:int = 0; i < accordion.numChildren; i++){
		sp = Sprite(accordion.getChildAt(i));
		TweenLite.to(sp,.5,{ x: i * barWidth});
	}
}

13 thoughts on “XML Horizontal Accordion Photos Gallery

  1. Pingback: Flash Tutorial : XML Horizontal Accordion Photos Gallery : All CG Tutorials

  2. earthflyer

    Excellent tutorial

    trying to understand AS3 for XML at the moment and this has been a good study.

    Thanks

  3. Simon

    Hello and thankyou so much for this great script.
    I’m trying to adapt it to handling swf files instead of images, but I’m lost as I’m new to AS3…
    Is there anyway you could help me out please?
    Tks a bunch!

  4. Simon

    Hello!

    Tks for that wonderful script 🙂

    Is it possible to adapt it so it can load also swf files?
    Thank you!!

  5. Christa

    I’m new to Actionscripting, so I apologize in advance.
    Is there a way to modify the action so that the xml file will allow the image to become a link to an external source?

    Thank you for the wonderful tutorial.

  6. Fernando

    Thanks for the great photo gallery and tutorial.
    Could you show us how to make each photo become a link to a new page?
    Best regards,
    Fernando

  7. Douglas

    Hi my question is the same of fernando, how i can put a external link or button in images with xml or Could you show us how to make each photo become a link to a new page or call a external file swf?

Leave a Reply

Your email address will not be published. Required fields are marked *