There are a variety of ways to create a Flash Photo Gallery depending upon you skill and experience. To select the code below and use it, double-click on the code and select copy and then paste it into the corresponding Flash version fla file in the ActionScript panel.
Download source files for Flash CS5 (Use code below for CS3 and CS4)
Version 1 is a stand alone file that uses redundant code with the images inside of the flash movie. The drawback to this approach is that you have to open up the Flash fla file any time you want to update an image or any of the text. Also, you have many frames along the timeline to contend with.
stop (); thumbnail1.addEventListener (MouseEvent.CLICK, showImage1); function showImage1 (event:MouseEvent):void { gotoAndStop ("image1"); } thumbnail2.addEventListener (MouseEvent.CLICK, showImage2); function showImage2 (event:MouseEvent):void { gotoAndStop ("image2"); } thumbnail3.addEventListener (MouseEvent.CLICK, showImage3); function showImage3 (event:MouseEvent):void { gotoAndStop ("image3"); } thumbnail4.addEventListener (MouseEvent.CLICK, showImage4); function showImage4 (event:MouseEvent):void { gotoAndStop ("image4"); } thumbnail5.addEventListener (MouseEvent.CLICK, showImage5); function showImage5 (event:MouseEvent):void { gotoAndStop ("image5"); } thumbnail6.addEventListener (MouseEvent.CLICK, showImage6); function showImage6 (event:MouseEvent):void { gotoAndStop ("image6"); }
Version 2 is better because it uses an array and a loop to create less code. Notice that the images layer now has a UILoader component and everything is done in one frame. Labels layer has been deleted and stop() method has been deleted from Actionscript. The code create an array and loop through this array to create functionality for each button via the onClick event handler.Buttons are given instance names that are the same as image names but without the extension (*.jpg).
var photoArray:Array = ["african_violets","bird_of_paradise","daffodils", "daisy_flowers","iris_flowers","lily_flowers"]; var totalPhotos:Number = photoArray.length; for (var i=0; i<totalPhotos; i++) { this[photoArray[i]].addEventListener (MouseEvent.CLICK, onClick); } function onClick (eventObject:MouseEvent):void { openingText.visible = false; imageLoader.load (new URLRequest("images/" + eventObject.target.name + ".jpg")); }
Version 3 is similar to Version 2 but the array and loop has been deleted. This code has each button listen for the same event handler function (i.e, onShowImage).
african_violets.addEventListener (MouseEvent.CLICK, onShowImage); bird_of_paradise.addEventListener (MouseEvent.CLICK, onShowImage); daffodils.addEventListener (MouseEvent.CLICK, onShowImage); daisy_flowers.addEventListener (MouseEvent.CLICK, onShowImage); iris_flowers.addEventListener (MouseEvent.CLICK, onShowImage); lily_flowers.addEventListener (MouseEvent.CLICK, onShowImage); function onShowImage (eventObject:MouseEvent):void { openingText.visible = false; imageLoader.load (new URLRequest("images/" + eventObject.target.name + ".jpg")); }
Version 4 is better because it is XML driven. The advantage of this approach is that you never have to open the Flash fla unless you need to change the layout or text design.
var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); trace (applicationData); for (var i:uint =0; i<6; i++) { //XML object has to be converted to a Object object var loadImage:Object = this[applicationData.image[i]]; //Add functionility to each button individually by looping loadImage.addEventListener (MouseEvent.CLICK,onShowImage); } } function onShowImage (eventObject:MouseEvent):void { openingText.visible = false; var completeName:String = "images/" + eventObject.target.name + ".jpg"; trace ("What is complete Name?" + completeName); imageLoader.load (new URLRequest(completeName)); }
BONUS: Add the following code that is highlighted (lines 1-3 and 27-47 to check if the XML is not found:
import flash.events.IOErrorEvent; import flash.text.TextField; import flash.text.TextFormat; var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); //trace (applicationData); for (var i=0; i<6; i++) { //Add functionility to each button individually by looping this[applicationData.image[i]].addEventListener (MouseEvent.CLICK,onShowImage); } } function onShowImage (eventObject:MouseEvent):void { //openingText.visible=false; Optional: Image will cover text. var completeName:String = eventObject.target.name + ".jpg"; //trace ("What is complete Name?" + completeName); myLoader.load (new URLRequest(completeName)); } loader.addEventListener (IOErrorEvent.IO_ERROR, onError); function onError (eventObject:IOErrorEvent):void { trace ("Error loading file."); var formatError:TextFormat = new TextFormat(); formatError.bold = true; formatError.color = 0x000000; formatError.size = 24; formatError.font = "Arial"; formatError.italic = true; var ErrorText:TextField = new TextField(); ErrorText.text = "The 'index.xml' file was NOT found!!!"; ErrorText.x = stage.stageWidth / 2;//Center text on stage ErrorText.y = 150; ErrorText.autoSize = TextFieldAutoSize.CENTER; ErrorText.setTextFormat (formatError); addChild (ErrorText); }
NOTE: This code checks to see if the XML file exist and if not display an error in a text field. Necessary classes are imported (lines 1-3) and a TextFormat object was created to format the text and a TextField object was created to "capture" the error message.
Version 4 (Expert 2) is the best because it dynamically load the thumbnails. This prevents you from having to open the Flash movie to add different thumbnails and having to change the conditional statement in the loop (i.e., i<6). In fact, the thumbnails is actually the larger image scaled down inside of several UILoader components. The buttons layer was deleted since the thumbnails will be created dynamically from code. The for loop (lines 13-27) and the onShowImage function (lines 32-35) were modified to accomodate for a more dynamic rendering of the thumbnails.
import flash.events.IOErrorEvent; import flash.text.TextField; import flash.text.TextFormat; var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); //trace (applicationData); var totalNodes:int = applicationData.image.length(); for (var i=0; i<totalNodes; i++) { var thumbnail:UILoader = new UILoader(); // The number 120 represents the button size (100) plus the gap(20) between each thumbnail. thumbnail.x = 65 + (i*120); thumbnail.y = 65; thumbnail.width = 100; thumbnail.height = 55; thumbnail.buttonMode = true; thumbnail.source = "images/" + applicationData.image[i] + ".jpg" thumbnail.scaleContent = true; thumbnail.maintainAspectRatio = false; addChild (thumbnail); //Add functionility to each button individually by looping thumbnail.addEventListener (MouseEvent.CLICK,onShowImage); } } function onShowImage (eventObject:MouseEvent):void { openingText.visible=false; var completeName:String = eventObject.currentTarget.source; trace ("What is complete Name?" + eventObject.currentTarget.source); imageLoader.load (new URLRequest(completeName)); } loader.addEventListener (IOErrorEvent.IO_ERROR, onError); function onError (eventObject:IOErrorEvent):void { trace ("Error loading file."); var formatError:TextFormat = new TextFormat(); formatError.bold = true; formatError.color = 0x000000; formatError.size = 24; formatError.font = "Arial"; formatError.italic = true; var ErrorText:TextField = new TextField(); ErrorText.text = "The 'index.xml' file was NOT found!!!"; ErrorText.x = stage.stageWidth / 2;//Center text on stage ErrorText.y = 150; ErrorText.autoSize = TextFieldAutoSize.CENTER; ErrorText.setTextFormat (formatError); addChild (ErrorText); }
BONUS: Add a highlight effect when a thumbnail is rollover or rollout by the mouse. Add highlighted code (lines 29-30 and 41-49):
import flash.events.IOErrorEvent; import flash.text.TextField; import flash.text.TextFormat; var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); //trace (applicationData); var totalNodes:int = applicationData.image.length(); for (var i=0; i<totalNodes; i++) { var thumbnail:UILoader = new UILoader(); // The number 120 represents the button size (100) plus the gap(20) between each thumbnail. thumbnail.x = 65 + (i*120); thumbnail.y = 65; thumbnail.width = 100; thumbnail.height = 55; thumbnail.buttonMode = true; thumbnail.source = "images/" + applicationData.image[i] + ".jpg"; thumbnail.scaleContent = true; thumbnail.maintainAspectRatio = false; addChild (thumbnail); //Add functionility to each button individually by looping thumbnail.addEventListener (MouseEvent.CLICK,onShowImage); thumbnail.addEventListener (MouseEvent.MOUSE_OVER,onMouseOver); thumbnail.addEventListener (MouseEvent.MOUSE_OUT,onMouseOut); } } function onShowImage (eventObject:MouseEvent):void { openingText.visible = false; var completeName:String = eventObject.currentTarget.source; trace ("What is complete Name?" + eventObject.currentTarget.source); imageLoader.load (new URLRequest(completeName)); } function onMouseOver (eventObject:MouseEvent):void { eventObject.target.alpha = .5; } function onMouseOut (eventObject:MouseEvent):void { eventObject.target.alpha = 1; } loader.addEventListener (IOErrorEvent.IO_ERROR, onError); function onError (eventObject:IOErrorEvent):void { trace ("Error loading file."); var formatError:TextFormat = new TextFormat(); formatError.bold = true; formatError.color = 0x000000; formatError.size = 24; formatError.font = "Arial"; formatError.italic = true; var ErrorText:TextField = new TextField(); ErrorText.text = "The 'index.xml' file was NOT found!!!"; ErrorText.x = stage.stageWidth / 2;//Center text on stage ErrorText.y = 150; ErrorText.autoSize = TextFieldAutoSize.CENTER; ErrorText.setTextFormat (formatError); addChild (ErrorText); }
What if the number of thumbnails exceed the width of the stage, what can you do? You can check the thumbnails as they are loaded and wrap any thumbnails to another row if they exceed the stage width. Note the stage and stage objects has been resized to accomodate another row of thumbnails. The <image> tags in the index.xml file has also been updated to accomodate two rows. Note that index2.xml is used instead of index.xml (line 6). In this XML file, the "."jpg" extenstion was added to each image so it does not have to be "hard-wired" in code. Add the following code (lines 27-35).
import flash.events.IOErrorEvent; import flash.text.TextField; import flash.text.TextFormat; var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index2.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); //trace (applicationData); var totalNodes:int = applicationData.image.length(); for (var i=0; i<totalNodes; i++) { var thumbnail:UILoader = new UILoader(); // The number 120 represents the button size (100) plus the gap(20) between each thumbnail. thumbnail.x = 65 + (i*120); thumbnail.y = 65; thumbnail.width = 100; thumbnail.height = 55; thumbnail.buttonMode = true; thumbnail.source = "images/" + applicationData.image[i]; thumbnail.scaleContent = true; thumbnail.maintainAspectRatio = false; if (thumbnail.x + thumbnail.width > stage.stageWidth) {// Since "i" is still incrementing, we need to substract a value (660) to start again. thumbnail.x = (i*120)- 660;//Get current y position of thumbnail, add its height and add a gap (20) thumbnail.y = thumbnail.y + thumbnail.height + 25; } else { thumbnail.y = 65;// row 1 only } addChild (thumbnail); //Add functionility to each button individually by looping thumbnail.addEventListener (MouseEvent.CLICK,onShowImage); thumbnail.addEventListener (MouseEvent.MOUSE_OVER,onMouseOver); thumbnail.addEventListener (MouseEvent.MOUSE_OUT,onMouseOut); } } function onShowImage (eventObject:MouseEvent):void { openingText.visible = false; var completeName:String = eventObject.currentTarget.source; trace ("What is complete Name?" + eventObject.currentTarget.source); imageLoader.load (new URLRequest(completeName)); } function onMouseOver (eventObject:MouseEvent):void { eventObject.target.alpha = .5; } function onMouseOut (eventObject:MouseEvent):void { eventObject.target.alpha = 1; } loader.addEventListener (IOErrorEvent.IO_ERROR, onError); function onError (eventObject:IOErrorEvent):void { trace ("Error loading file."); var formatError:TextFormat = new TextFormat(); formatError.bold = true; formatError.color = 0x000000; formatError.size = 24; formatError.font = "Arial"; formatError.italic = true; var ErrorText:TextField = new TextField(); ErrorText.text = "The 'index.xml' file was NOT found!!!"; ErrorText.x = stage.stageWidth / 2;//Center text on stage ErrorText.y = 150; ErrorText.autoSize = TextFieldAutoSize.CENTER; ErrorText.setTextFormat (formatError); addChild (ErrorText); }
While two rows of thumbnails is great, let's take this a step further by using a "for" loop with an "if" statement to create a series or rows and columns. Notice that only the column variable has to be changed--the rows are automatically calculated based on the number of images loaded. Code for lines 9-17 were added as well as the onDataLoad "for" loop has been modified (lines 25-51). Line 85 was as modified slightly.
import flash.events.IOErrorEvent; import flash.text.TextField; import flash.text.TextFormat; var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index2.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); var COLUMNS:uint = 5; var CELL_WIDTH:uint = 100 var CELL_HEIGHT:uint = 55 var GAP_BETWEEN_CELL:uint = 10 var MARGIN_RIGHT:uint = 50; var MARGIN_TOP:uint = 75; var x_counter:uint = 0; var y_counter:uint = 0; var PathToImageFolder:String = "images/" function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); //trace (applicationData); var totalNodes:int = applicationData.image.length(); for (var i=0; i<totalNodes; i++) { var thumbnail:UILoader = new UILoader(); thumbnail.width = CELL_WIDTH; thumbnail.height = CELL_HEIGHT; thumbnail.buttonMode = true; thumbnail.source = PathToImageFolder + applicationData.image[i]; thumbnail.scaleContent = true; thumbnail.maintainAspectRatio = false; thumbnail.x = MARGIN_RIGHT +(thumbnail.width + GAP_BETWEEN_CELL)*x_counter; thumbnail.y = MARGIN_TOP + (thumbnail.height + GAP_BETWEEN_CELL)*y_counter ; if (x_counter+1 < COLUMNS) { x_counter++; } else { x_counter = 0; y_counter++; } addChild (thumbnail);//Add functionility to each button individually thumbnail.addEventListener (MouseEvent.MOUSE_DOWN,onShowImage); thumbnail.addEventListener (MouseEvent.MOUSE_OVER,onMouseOver); thumbnail.addEventListener (MouseEvent.MOUSE_OUT,onMouseOut); } } function onShowImage (eventObject:MouseEvent):void { openingText.visible = false; var completeName:String = eventObject.currentTarget.source; trace ("What is complete Name?" + eventObject.currentTarget.source); imageLoader.load (new URLRequest(completeName)); } function onMouseOver (eventObject:MouseEvent):void { eventObject.target.alpha = .5; } function onMouseOut (eventObject:MouseEvent):void { eventObject.target.alpha = 1; } loader.addEventListener (IOErrorEvent.IO_ERROR, onError); function onError (eventObject:IOErrorEvent):void { trace ("Error loading file."); var formatError:TextFormat = new TextFormat(); formatError.bold = true; formatError.color = 0x000000; formatError.size = 24; formatError.font = "Arial"; formatError.italic = true; var ErrorText:TextField = new TextField(); ErrorText.text = "The 'index2.xml' file was NOT found or is corrupted!!!"; ErrorText.x = stage.stageWidth / 2;//Center text on stage ErrorText.y = 150; ErrorText.autoSize = TextFieldAutoSize.CENTER; ErrorText.setTextFormat (formatError); addChild (ErrorText); }
Let's convert the procedual code to object oriented code. To do this, we need to perform the following steps (See complete code below steps):
package { import flash.text.*; //import flash.text.TextField; //import flash.text.TextFormat; //import flash.text.TextFieldAutoSize; import flash.events.*; //import flash.events.IOErrorEvent; //import flash.events.MouseEvent; //import flash.events.Event; import flash.net.*; //import flash.net.URLLoader; //import flash.net.URLRequest; import flash.display.*; //import flash.display.MovieClip; //import flash.display.Sprite; public class PhotoGallery extends MovieClip { private var COLUMNS:uint = 5; private var CELL_WIDTH:uint = 100; private var CELL_HEIGHT:uint = 55; private var GAP_BETWEEN_CELL:uint = 10; private var MARGIN_RIGHT:uint = 50; private var MARGIN_TOP:uint = 75; private var x_counter:uint = 0; private var y_counter:uint = 0; private var PathToImageFolder:String = "images/"; private var imageContainer:Sprite; public function PhotoGallery () { var loader:URLLoader = new URLLoader(); loader.load (new URLRequest("index2.xml")); loader.addEventListener (Event.COMPLETE, onDataLoad); loader.addEventListener (IOErrorEvent.IO_ERROR, onError); } public function onDataLoad (eventObject:Event):void { var applicationData:XML = new XML(eventObject.target.data); //trace (applicationData); var totalNodes:int = applicationData.image.length(); for (var i=0; i<totalNodes; i++) { //Create a new container and add a border in it. imageContainer = new Sprite(); imageContainer.graphics.lineStyle (2, 0xFFFFFF); imageContainer.graphics.beginFill (0x00FF00, 0); imageContainer.graphics.drawRect (0,0,100,55); var thumbnail:UILoader = new UILoader(); thumbnail.width = CELL_WIDTH; thumbnail.height = CELL_HEIGHT; thumbnail.buttonMode = true; thumbnail.source = PathToImageFolder + applicationData.image[i]; thumbnail.scaleContent = true; thumbnail.maintainAspectRatio = false; imageContainer.x = MARGIN_RIGHT +(thumbnail.width + GAP_BETWEEN_CELL)*x_counter; imageContainer.y = MARGIN_TOP + (thumbnail.height + GAP_BETWEEN_CELL)*y_counter; if (x_counter + 1 < COLUMNS) { x_counter++; } else { x_counter = 0; y_counter++; } imageContainer.addChild (thumbnail); //Add functionility to each button individually; addChild (imageContainer); thumbnail.addEventListener (MouseEvent.MOUSE_DOWN,onShowImage); thumbnail.addEventListener (MouseEvent.MOUSE_OVER,onMouseOver); thumbnail.addEventListener (MouseEvent.MOUSE_OUT,onMouseOut); } } public function onShowImage (eventObject:MouseEvent):void { openingText.visible = false; var completeName:String = eventObject.currentTarget.source; trace ("What is complete Name?" + eventObject.currentTarget.source); imageLoader.load (new URLRequest(completeName)); } public function onMouseOver (eventObject:MouseEvent):void { eventObject.target.alpha = .5; //eventObject.target.graphics.lineStyle (2, 0xFF0000); //addChild(imageContainer) } public function onMouseOut (eventObject:MouseEvent):void { eventObject.target.alpha = 1; } public function onError (eventObject:IOErrorEvent):void { trace ("Error loading file."); var formatError:TextFormat = new TextFormat(); formatError.bold = true; formatError.color = 0x000000; formatError.size = 24; formatError.font = "Arial"; formatError.italic = true; var ErrorText:TextField = new TextField(); ErrorText.text = "The 'index2.xml' file was NOT found or is corrupted!!!"; ErrorText.x = stage.stageWidth / 2;//Center text on stage ErrorText.y = 150; ErrorText.autoSize = TextFieldAutoSize.CENTER; ErrorText.setTextFormat (formatError); addChild (ErrorText); } } }
(Bonus) Just to demostrate that you can insert an object inside of other object, the border code has be deleted from the code and defined in a separate class and then instantiated in to code. Download the zip below and extract the two files from it in the same project folder. Then change the document type from PhotoGallery1 to PhotoGallery2 in the Flash movie.
ImageContainerAndPhotoGallery2