Chapter 36. Building an Image Gallery Component

IN THIS CHAPTER

  • Planning and scoping a component

  • Using filter effects with components

  • Storing image information as BitmapData

  • Integrating the Tween class

  • Scripting XML data with PHP

In the first two chapters of Part IX, you learned how to use many of the user interface and data components of Flash CS3. Now that you're familiar with common production tasks associated with components, you can start to learn how to create your own custom components. In this chapter, you learn how to build a Gallery component. By the end of this chapter, you will know the steps and procedures required to build a fully functional component.

In this chapter, you learn how to build a Flash movie that can dynamically load a list of JPEG files that the user can browse as a series of thumbnails. When the user clicks one of the thumbnails, a larger version of the image loads into the Flash movie. To see the final project, open your Web browser and go to:

www.flashsupport.com/fb/as2/gallery

Note

Make sure you have Flash Player 8 or higher installed to view the completed project.

At this location, you see the interface shown in Figure 36.1. When you click an image thumbnail, the original JPEG loads into the area below the thumbnail bar. The active selection within the bar is highlighted with a bevel filter. When you click another thumbnail, the previously selected thumbnail transitions to a muted grayscale version.

The completed project

Figure 36.1. The completed project

Creating a Plan

Before you can start to build the Gallery component, you need to plan the scope of the project. Just what will the component do? We distill the planning process by telling you the component's features, but in the real world, you will need to brainstorm your ideas and formulate directives for a workable production schedule, accountable to your client's budget and your time.

Note

Read Chapter 3, "Planning Flash Projects," for more information on production guidelines for Flash projects.

Describing the feature set

It might sound too simple to state, but you have to have a plan before you can build anything— even a Flash movie. And more often than not, the lack of proper planning before you start to build a Flash project only results in bigger problems later— the kind that keep you up late at night days before the final delivery date. One of the most common problems that arise early in a Flash project is the desire to overbuild, or add more features to a project than are necessary to satisfy the goals of the project.

The goals we're aiming to fulfill with the Gallery component include:

  • Quick updates to images on the server: Many of your business clients love the capability to just upload some images to a Web server, and voila— the images are automatically loading into a Flash user interface you designed for them. One of the goals of this project, therefore, is to use server-side scripting (in this case, using PHP as the server-side language) to dynamically read the filenames in a given Web folder and deliver that data to the Flash movie. Whenever a new JPEG file is uploaded to that Web folder, the PHP script automatically includes the file in the XML feed it sends to the Flash movie.

  • Unique yet usable interface for browsing images: At the end of the day, if your Flash movie's user interface is too confusing for a Web visitor to understand, the project has lost the potential that Flash offers over standard HTML-based sites. The Gallery component should indicate the state of image browsing clearly, with rollover and rollout states for thumbnail buttons. The thumbnails should also remember if they've been clicked previously or not.

  • Downloadable images: If a user likes an image, she should be able to download the image to the desktop. In this component, you learn how to use the new FileReference API to download files directly from a Flash Player 8 or higher movie. You use this new feature with the ContextMenu class to enable the user to right-click the large image area to download the JPEG file currently displayed.

    Tip

    In ActionScript 2.0, you can also use the FileReference API to upload files from the user's computer to your Web server.

  • Utilizing JPEG metadata: If you've used a digital camera, you know that JPEG images can store a lot of useful data related to the exposure, camera model, flash settings, and so on. You can also use an application like Adobe Photoshop to add more metadata, such as a caption and an author byline. If the JPEG image displayed in the Gallery component has a caption, the component should display the caption below the image.

  • Dynamic resizing of original JPEG files for thumbnails: With the power of server-side scripting, you can create dynamically resized JPEG images on the fly— without ever having to manually create a thumbnail version yourself in a program like Adobe Photoshop. The Gallery component will feature a property that specifies the URL to a resizing script.

Determining the server-side scripting requirements

As we mentioned in the previous section, our Gallery component requires the power of server-side scripting to work its magic. We picked PHP as the server-side language to use for this project, although you could adapt the same functionality with any server-side language, including Macromedia ColdFusion, Microsoft .NET/ASP, Perl, and so on. One of the reasons we use PHP for this project is that PHP is available on practically every Web account that you purchase from an Internet Service Provider (ISP) or Internet Presence Provider (IPP). The following list provides the server-side requirements for this project.

Note

You can upload the info.php document to your Web server account to discover more details about your server's PHP installation. You can find this file in the ch36/finished files/prod/wwwroot folder of this book's CD-ROM.

  • PHP5: We recommend that you use PHP5 for this project, but you should be able to use PHP4 as well.

  • GD library: This library enables your PHP scripts to manipulate image data, including the capability to resize JPEG images. Without this library, you won't be able to create the thumbnail images for the Gallery component. If you run the info.php script on your Web server, search for the term "gd" to see if the GD library is installed, as shown in Figure 36.2.

After you've determined that your server has met the core requirements, you're ready to use the three PHP scripts we've included in the ch36/finished files/prod/wwwroot folder on this book's CD-ROM.

Tip

You can quickly determine if your Web server has PHP installed and enabled. Upload the info.php script to a publicly accessible folder on your Web server, and access the info.php script in a Web browser. If the browser asks you to download the info.php file, your Web server most likely does not have PHP enabled.

The GD library information as displayed by the info.php script.

Figure 36.2. The GD library information as displayed by the info.php script.

Note

It's beyond the scope of this chapter to discuss the PHP scripting used in each script file. We provide a basic overview of the each file's functionality in the following sections. We encourage you to open the PHP files in your preferred text editor to review the syntax. For the PHP experts out there, note that the $doc_root variable (found in both the files.php and resize.php scripts) uses a nonstandard way — for portability reasons— to determine the document root of the Web server. The syntax we use enables the scripts to function properly in both Windows IIS server and Apache Web server environments. Feel free to modify any of the scripts to suit your particular needs.

files.php

This script dynamically reads a specified Web folder to search for JPEG files and displays the found JPEG files in an XML document. You must pass a directory name, either relative or from the server root, as a variable named dir. For example, if you specify

files.php?dir=images/

the script looks for a folder named images in the same folder where the files.php script resides. You can also specify a directory with the syntax:

files.php?dir=/gallery/images/

which tells the script to look for a folder named gallery at the server root, and then looks for a folder named images within that gallery folder.

To see a sample XML document created by this script, type the following URL into a Web browser:

www.flashsupport.com/f8b/gallery/files.php?dir=images/

When this page loads, you should see the XML data shown in Listing 36.1. Note that the

files.php

Note

In order for the files.php script to function properly, the JPEG-Meta.php script must be located in the same Web folder as the files.php file. We discuss the JPEG-Meta.php script later in this section.

The XML data provided by the files.php script is loaded into the Flash movie, which turns the XML data into an array to pass as a data provider to the Gallery component.

Example 36.1. The XML Data for the JPEG Files

<?xml version="1.0" encoding="utf-8"?>
<gallery>
   <img width="500" height="200" src="images/darkPine.jpg" caption="Dark 
The XML Data for the JPEG Files
pine and setting sun, Griffith Park, CA" filename="darkPine.jpg" /> <img width="500" height="200" src="images/dustHalo.jpg" caption="Dust
The XML Data for the JPEG Files
halo on small tree, Griffith Park, CA" filename="dustHalo.jpg" /> <img width="500" height="200" src="images/dustyClearing.jpg"
The XML Data for the JPEG Files
caption="Dusty clearing with slanting sun, Runyon Canyon Park, CA"
The XML Data for the JPEG Files
filename="dustyClearing.jpg" /> <img width="500" height="200" src="images/japaneseTree.jpg"
The XML Data for the JPEG Files
caption="Japanese tree in fog, Runyon Canyon Park, CA"
The XML Data for the JPEG Files
filename="japaneseTree.jpg" /> <img width="500" height="200" src="images/rainbowTower.jpg"
The XML Data for the JPEG Files
caption="Rainbow sky and metal tower, Hollywood Hills, CA"
The XML Data for the JPEG Files
filename="rainbowTower.jpg" /> <img width="500" height="200" src="images/roadNorth.jpg"
The XML Data for the JPEG Files
caption="Road north to Mulholland Drive, Runyon Canyon, CA"
The XML Data for the JPEG Files
filename="roadNorth.jpg" /> <img width="500" height="200" src="images/scrolledRoot.jpg"
The XML Data for the JPEG Files
caption="Scrolled root at dusk, San Fernando Valley, CA"
The XML Data for the JPEG Files
filename="scrolledRoot.jpg" /> <img width="500" height="200" src="images/skyPools.jpg"
The XML Data for the JPEG Files
caption="Rain pools under cloudy sky, Runyon Canyon Park, CA"
The XML Data for the JPEG Files
filename="skyPools.jpg" /> <img width="500" height="200" src="images/valleyOverlook.jpg"
The XML Data for the JPEG Files
caption="Overlook, San Fernando Valley, CA"
The XML Data for the JPEG Files
filename="valleyOverlook.jpg" /> <img width="500" height="200" src="images/weepingTree.jpg"
The XML Data for the JPEG Files
caption="Weeping dark tree, Mulholland Drive, CA"
The XML Data for the JPEG Files
filename="weepingTree.jpg" /> <img width="500" height="200" src="images/wiredCity.jpg"
The XML Data for the JPEG Files
caption="Phone poles and palms, Hollywood, CA" filename="wiredCity.jpg" /> <img width="500" height="200" src="images/wiredHill.jpg"
The XML Data for the JPEG Files
caption="Dark hills and paths under wires, Los Angeles, CA"
The XML Data for the JPEG Files
filename="wiredHill.jpg" /> </gallery>

resize.php

This PHP script performs the task of resizing a copy of the original JPEG image to fit a specific height. In this project, the Gallery component's thumbnails should be 50 pixels tall. The resize.php script requires two parameters: height and img. The height parameter should be an integer value, while the img parameter specifies the path and name of the JPEG file to resize. For example, if you type the following URL into a Web browser, you should see a picture of a beach on Prince Edward Island, Canada, resized to a height of 50 pixels:

www.flashsupport.com/fb/as2/gallery/resize.php?height=50&img=/images/beach.jpg

With the Gallery component, you can specify the resize.php script as the value of the thumbScript property.

Tip

You can quickly determine if you have the GD library installed (and/or enabled) on your Web server by uploading the resize.php script to a publicly accessible folder and accessing the script in the Web browser as we demonstrated with the beach picture. Specify an img path that points to a JPEG you've uploaded to another folder on the server.

JPEG-Meta.php

This amazing script, provided to us by Rob Williams at CommunityMX.com, enables the files.php script to retrieve the metadata, if any exists, of each JPEG file in the specified folder. This script must be uploaded to the same Web folder as the files.php script. Without this file, the files.php script does not function.

Note

For more information about using Rob William's PHP script, read his tutorial at CommunityMX.com. You can find a link to this tutorial in the PHP Utilities section of the www.flashsupport.com/links page.

Note

You also need to upload the JPEG images to your Web server, into a folder whose path you specify with the files.php script from the Flash movie.

Phase 1: Setting Up the Gallery Class

On this book's CD-ROM, in the ch36 folder, you can find two folders: starter files and finished files. Each folder has the same structure, featuring dev and prod folders. The dev folder contains all of the source files, such as .fla files and ActionScript files, while the prod folder contains all of the Web-ready files that should be uploaded to the Web server for final deployment.

Note

You can learn more about our dev and prod folder structures in Chapter 3, "Planning Flash Projects."

The starter files and finished files folders also have their own version of the gallery.flp file, which is a Flash Project file. In Flash CS3, you can open these .flp files to see the dev and prod folder structures. The gallery.flp file from the starter files folder is shown in Figure 36.3.

The gallery.flp file from the starter files folder

Figure 36.3. The gallery.flp file from the starter files folder

Reviewing the starter files

Let's review the files that have already been built in the starter files folder. You can access each of these files from the gallery.flp file in the Project panel.

Proxy.as

This ActionScript 2.0 class file, found in the dev/flash/ascb/utils folder, enables a class named Proxy, which has a create() method. This class is very similar to the Delegate class we have used with several ActionScript 2.0 examples in previous chapters of the books. The advantage of using the Proxy.create() method over the Delegate.create() method is that the Proxy.create() method enables you to pass additional parameters to the proxied (or delegated) function. For example, with the Delegate class, you can only specify a scope and a handler

import mx.utils.Delegate;

var myButton:MovieClip;

myButton.onRelease = Delegate.create(this, onButtonClick);

function onButtonClick():Void {
   trace("onButtonClick >");
}

which instructs the onRelease() handler of the MovieClip instance named myButton to invoke the onButtonClick() function whenever the myButton instance is clicked. However, with the Proxy class, you can pass one or more parameters to the proxied function. In the following example, the onButtonClick() function receives a reference to the myButton instance:

import ascb.util.Proxy;

var myButton:MovieClip;

myButton.onRelease = Proxy.create(this, onButtonClick, myButton);

function onButtonClick(mc:MovieClip):Void {
   trace("onButtonClick >");
   trace("	clicked instance: " + mc);
}

For the Gallery component, you use the Proxy class to delegate events for several handlers, including the User Interface components and the thumbnail image buttons.

Note

Many thanks to Joey Lott, co-author of the Flash ActionScript Bible series (Wiley), for providing us with his Proxy.as class. You can find more information about Joey and his books at www.person13.com.

EasyFilter.as

This class file, which can be found in the dev/flash/com/themakers/Effects folder, contains one method named saturate. This method can create a ColorMatrixFilter instance. This filter is the ActionScript class responsible for enabling the new Adjust Color filter available for MovieClip and TextField instances in the Filters tab of the Property inspector. For the Gallery component, you use the EasyFilter.saturate() method to easily control the saturation color values of thumbnail images. The saturate() method accepts values from −100 to 100, just like the Saturation slider in the Adjust Color filter of the Filters tab of the Property inspector. The following code sample illustrates a typical use of the method:

import com.themakers.Effects.EasyFilter;

var myButton:MovieClip;
myButton.filters = [EasyFilter.saturate(−50)];

Note

Many thanks to Joey Lott and Guy Watson for their help with creating the ActionScript code within the saturate() method. It's beyond the scope of this book to discuss the intricacies of using matrix values with the ColorMatrixFilter class— look to the Flash 8 ActionScript Bible by Joey Lott (Wiley, 2006) for more information.

main_starter.fla

This Flash document contains the basic layout for the Gallery component and can be found in the ch36/starter files/dev/flash/main_starter.fla folder. If you open this file, you can see that the Main Timeline of the movie has three layers:

  • _captionField: This layer has a TextField instance of the same name. The instance is located near the bottom of the Stage. This field displays the caption text for the JPEG image. This field also embeds most of the Basic Latin characters for the Arial font, and the field uses the new Anti-alias for readability setting in the Property inspector. Note that not all JPEG images have caption metadata— we specifically added caption data to each sample JPEG image in the project, using Adobe Photoshop's File

    main_starter.fla
  • _scrollPane: This layer has a ScrollPane component of the same name. The instance is located at the top of the Stage. The ScrollPane instance stores MovieClip holders for each of the loaded JPEG thumbnail images.

  • _loader: This layer has a Loader component of the same name. The instance is located below the ScrollPane instance. When a user clicks a thumbnail image in the ScrollPane instance, the full-size JPEG image loads and scales within the width and height of the Loader instance.

The Publish Settings for the main_starter.fla file have already been set up to publish the .swf and .html files for the document to the prod/wwwroot folder. The .swf file is named main.swf, and the .html file is named main.html. Both of these files have already been added to the gallery.flp file.

Constructing the Gallery component

Before you start to modify the starter files, create a copy of the starter files folder on your computer. In the following steps, you learn how to create a Gallery class file for the Gallery component. Then, you associate the class with a new Gallery clip in the Library panel.

Note

Make a copy of the ch36/starter files folder on your computer.

  1. Browse to the dev/flash/com/themakers folder in the starter files folder you copied.

  2. Create a new folder named Portfolio. This folder is used to store the Gallery.as file you create in the next steps. This folder could also be used to store other class files related to a Portfolio set of components, such as a gallery chooser.

  3. In Flash CS3, open the gallery.flp file in the starter files folder you copied.

  4. Create a new ActionScript document by choosing File

    Constructing the Gallery component
  5. In the Gallery.as script file, add the code shown in Listing 36.2. This code imports all of the necessary classes that the Gallery class requires and creates the constructor for the class. We discuss many of the imported classes as we add further portions of code to the class. For now, you declare three private variables representing the three elements currently on the Stage of the main_starter.fla document. The constructor invokes the init() function, which contains a trace() action to indicate that the class has instantiated.

    Example 36.2. The Gallery Class Constructor

    import ascb.util.Proxy;
    import flash.display.BitmapData;
    import flash.filters.*;
    import flash.net.FileReference;
    import mx.transitions.Tween;
    import com.themakers.Effects.EasyFilter;
    
    class com.themakers.Portfolio.Gallery extends MovieClip {
    
       private var _scrollPane:mx.containers.ScrollPane;
       private var _loader:mx.controls.Loader;
       private var _captionField:TextField;
    
       function Gallery(){
          init();
       }
       private function init():Void {
          trace("Gallery.init >");
       }
    
    }
  6. Save the Gallery.as file.

  7. In the Project panel, double-click the main_starter.fla file.

  8. In the Timeline window, select all the frames, from top to bottom, across the three layers. Right-click (or Control+click on Mac) the frame selection, and choose Copy Frames from the contextual menu.

  9. Choose Insert

    The Gallery Class Constructor

    Tip

    Alternatively, you can assign global class paths in the Flash tab of the Publish Settings dialog box— click the Settings button next to the ActionScript Version menu.

  10. In the new timeline of the Gallery symbol, select frame 1 of Layer 1. Right-click (or Control+click on Mac) the frame, and choose Paste Frames. The elements from the Main Timeline should now be pasted into the Gallery symbol timeline. Note that the layer names are automatically copied as well.

  11. With all of the elements selected on the Stage, open the Property inspector. The elements are not aligned to the top-left corner of the symbol's registration point. In general, it's considered best practice to align elements within components to the top-left corner. In the Property inspector, change the X position to 0 and the Y position to 0. When you deselect the elements on the Stage, the registration point should be at the top-left corner of the ScrollPane component.

  12. Believe it or not, that's all you need to do on the timeline of the Gallery symbol. Everything else happens within the Gallery.as file. Remember, because you attached the Gallery class in the AS 2.0 Class field for the Gallery clip, all of the code within the class file is automatically associated with the symbol.

    Tip

    If you want to change the embedded font used for caption text, select the _captionField instance on the Stage of the Gallery clip and change the font name in the Property inspector.

  13. Go back to the Main Timeline (Edit

    The Gallery Class Constructor
    The Create New Symbol dialog box

    Figure 36.4. The Create New Symbol dialog box

  14. Open the Library panel (Ctrl+L or

    The Create New Symbol dialog box
  15. To make sure the Gallery.as class file is attaching correctly to the Gallery symbol, save the Flash document, and test it (Ctrl+Enter or

    The Create New Symbol dialog box

Note

You can find this version of the main_starter.fla file as main_100.fla in the ch36/in_process folder. The Listing36-1.as file located in the ch36 folder can be renamed to Gallery.as and inserted into your Portfolio folder.

Phase 2: Loading Thumbnails into the ScrollPane

In this section, you learn how to modify the Gallery.as and main_starter.fla files to load JPEG thumbnails from your PHP server.

Uploading scripts and images to your Web server

Before you can continue to modify the Flash documents for this project, you need to upload the files in the starter files/prod/wwwroot folder to a publicly accessible location on your PHP-enabled Web server. If possible, try uploading the files to the document root of the Web server. For example, if your site's domain is www.mydomain.com, try putting the PHP script files at the document root where you can load them by typing the following URL into a Web browser:

http://www.mydomain.com/info.php

Also, if you have directory browsing enabled on your Web server, you should be able to access the images folder (and browse the image files within) by typing:

http://www.mydomain.com/images

After you've completed the project, you can move your script files and images to other folders and modify the script parameters in the Flash movie as needed.

Tip

You can also configure a local Web server on your computer for testing purposes. During the writing of this chapter, we used PHP5 with Microsoft IIS on Windows XP. If you test locally, make sure that http://localhost/info.php loads properly before continuing.

Building data properties for the Gallery class

Once you have uploaded the wwwroot files to your own Web server, you're ready to go back to Flash production tasks. In this section, you add several data properties to the component, enabling the component to access the resize.php script and to store the JPEG file information for the Gallery.

  1. Go back to the Gallery.as file you created in Phase 1. Add the bold code shown in Listing 36.3. This new code creates the following properties. Each property has an associated private variable listed at the top of the class.

    • items: This property saves an array of JPEG filenames in the _data private variable. The items property is accessed later in this chapter when the thumbnails are built. Whenever information related to the active thumbnail or JPEG image displayed in the Loader component is needed, the items property can be utilized.

    • rootURL: This property stores a root path to the Web server with the PHP scripts and images. This value is appended to image URLs used throughout the class. The private variable _rootURL stores the String data associated with this property.

    • thumbScript: This property stores the name of the script file to call for dynamic resizing of the JPEG images as thumbnails. The default value is set to resize.php, the script file you've already put on your Web server.

    • thumbURL: This read-only property formats the thumbScript value with the rootURL value, the thumbHeight value for the height= variable for the resize.php script, and the img= variable required by the resize.php script. The actual image name is appended to thumbURL in a later function. The String value for this property is stored in the private variable _thumbScript.

    • thumbHeight: This property stores the height, in pixels, that should be passed to the resize.php script for the creation of the thumbnail images. The private variable _thumbHeight stores the value for this property.

    Note

    Any property that is preceded by an [Inspectable] tag will be available in the Parameters tab of the Property inspector for the Gallery component. You won't see such properties appear unless you specify the AS 2.0 class name in the Component Definition dialog box, which we discuss later in this chapter.

    Also, while the use of the underscore ( _ ) for private variable names used within a class is a common practice, you can name your private variables with your own custom naming convention.

    Example 36.3. The Data Properties of the Gallery Class

    import ascb.util.Proxy;
    import flash.display.BitmapData;
    import flash.filters.*;
    import flash.net.FileReference;
    import mx.transitions.Tween;
    import com.themakers.Effects.EasyFilter;
    
    class com.themakers.Portfolio.Gallery extends MovieClip {
    
       private var _scrollPane:mx.containers.ScrollPane;
       private var _loader:mx.controls.Loader;
       private var _captionField:TextField;
       private var _data:Array;
       private var _rootURL:String;
       private var _thumbScript:String;
       private var _thumbHeight:Number;
    
       function Gallery(){
          init();
       }
    
       private function init():Void {
          trace("Gallery.init >");
       }
    
       public function set items(val:Array):Void {
          _data  = val;
       }
    
       public function get items():Array {
                       return _data;
       }
    
       [Inspectable(defaultValue="",name="Server Host")]
       public function set rootURL(path:String):Void {
           _rootURL = path;
       }
    
       public function get rootURL():String {
    return _rootURL != undefined ? _rootURL : "";
       }
          [Inspectable(defaultValue="resize.php")]
       public function set thumbScript(path:String):Void {
          _thumbScript = path;
       }
       public function get thumbScript():String {
          return _thumbScript;
       }
       public function get thumbURL():String {
          return rootURL +thumbScript + "?height=" + thumbHeight + "&img=";
       }
    
       [Inspectable(defaultValue=50)]
       public function set thumbHeight(val:Number):Void {
          _thumbHeight = val;
       }
    
       public function get thumbHeight():Number {
          return _thumbHeight;
       }
  2. Save the Gallery.as file.

Creating thumbnail holders in the Gallery class

After you've created the data properties for the Gallery class, you're ready to add the code that makes new MovieClip holders within the nested ScrollPane instance, _scrollPane, of the Gallery symbol.

  1. In the Gallery.as file, add the bold code shown in Listing 36.4. Note that the

    Creating thumbnail holders in the Gallery class
    • init: The init() function now sets a private variable named _thumbSpacing. This variable stores the number of pixels to insert between thumbnail images. You can change this number to increase or decrease the horizontal gap between thumbnails.

    • onLoad: Because we have placed author-time instances of the User Interface components on the Stage of the Gallery symbol, we need to use the MovieClip.onLoad() handler to properly initialize any parameters with the ScrollPane (_csp) or Loader (_clo) components. Here, the stylePane() function is invoked to format the ScrollPane instance.

      Note

      Because the Gallery class extends the MovieClip class (see the class statement at the top of the file), the onLoad function automatically invokes when the Gallery instance appears within the Flash movie at runtime. You don't explicitly call the onLoad() function anywhere within the class.

    • stylePane: This function sets the background color and border style of the ScrollPane instance. More importantly, the contentPath property of the ScrollPane instance is set to paneHolder. As you see in the buildHolders() function, you need to create new MovieClip instances within the ScrollPane instance— you can't add content within the ScrollPane instance without building an empty MovieClip symbol in the movie's Library that is attached to the ScrollPane instance. You build the paneHolder symbol later in this section.

    • buildHolders: This function goes through the items property (which contains a list of all the JPEG file information) and builds nested MovieClip instances within the ScrollPane instance's content clip. Each MovieClip instance for a thumbnail (the mc instance) is created within a MovieClip named _imgColl (short for image collection), which is also a private variable for the Gallery class. This variable is accessed later for finding thumbnails and controlling their states. Each mc instance has a nested MovieClip instance named img, which is targeted with a MovieClipLoader instance named _mcl, which is also a private variable name. Each object in the items array contains a src property (mapped from the XML generated by the files.php script), which is used as the img variable value to format the URL for the resize.php script.

    • calcThumbW: This function is used within the buildHolders() function to determine how wide a thumbnail image should be based on the aspect ratio of the original image. The width and height properties of the JPEG file are retrieved from nested objects within the items array.

      Note

      You haven't actually loaded any data into the Gallery instance back in the main_starter.fla file. In the next few steps, you learn how to load the XML data and format it as a data provider for the items property.

    • load: This public function initiates the thumbnail creation and loading process. This is the only method that needs to be called outside of the class.

    Note

    The properties added in Listing 36.4 are not displayed in the printed listing, but the complete code is available in the Listing36-4.as file in the ch36 folder of this book's CD-ROM.

    Example 36.4. The Thumbnail Creation Process

    import ascb.util.Proxy;
    import flash.display.BitmapData;
    import flash.filters.*;
    import flash.net.FileReference;
    import mx.transitions.Tween;
    import com.themakers.Effects.EasyFilter;
    
    class com.themakers.Portfolio.Gallery extends MovieClip {
    
       private var _scrollPane:mx.containers.ScrollPane;
       private var _loader:mx.controls.Loader;
       private var _captionField:TextField;
       private var _data:Array;
       private var _rootURL:String;
       private var _thumbScript:String;
       private var _thumbSpacing:Number;
       private var _thumbSpacing:Number;
       private var _mcl:MovieClipLoader;
       private var _imgColl:MovieClip;
    
       function Gallery(){
    init();
       }
       private function init():Void {
          trace("Gallery.init >");
          _thumbSpacing = 1;
       }
    
        private function onLoad():Void {
          stylePane();
       }
       private function stylePane():Void {
          _scrollPane.setStyle("backgroundColor", 0xFFFFFF);
          _scrollPane.setStyle("borderStyle", "none");
    
          _scrollPane.contentPath = "paneHolder";
       }
       private function buildHolders():Void {
          var holder:MovieClip =  _scrollPane.content;
           _mcl = new MovieClipLoader();
          _mcl.addListener(this);
          var files:Array = items;
          var w:Number = 0;
          var coll:MovieClip = _imgColl = holder.createEmptyMovieClip(
    "_imgColl",
                      1
                                                );
    
    
          for(var i:Number = 0; i < files.length; i++){
             var item:Object = files[i];
             var mc:MovieClip =  coll.createEmptyMovieClip(
                                                          "image_" + i,
                                            i+1
                                           );
             mc._x = (i == 0) ? 0 : coll["image_" + (i-1)]._x + ;
               calcThumbW(files[i-1]) + _thumbSpacing;
          var disp:MovieClip = mc.createEmptyMovieClip("disp", 1);
             var imgH:MovieClip = disp.createEmptyMovieClip("imgH", 1);
         var img:MovieClip = imgH.createEmptyMovieClip("img", 1);
             mc.idx = i;
             var path:String = thumbURL + escape(item.src);
             _mcl.loadClip(path, img);
          }
        }
       private function calcThumbW(file:Object):Number {
    
                   var w:Number = file.width;
                   var h:Number = file.height;
                   var factor:Number = thumbHeight/h;
          return w*factor;
    }
        public function load():Void {
          buildHolders();
        }
    
       [Public properties omitted from this listing...]
     }
  2. Save the Gallery.as file.

  3. Switch over to the main_starter.fla document. As we mentioned earlier in this section, you need to create an empty Movie Clip symbol named paneHolder, to use as a holder within the ScrollPane component. Choose Insert

    The Thumbnail Creation Process
    The paneHolder clip settings

    Figure 36.5. The paneHolder clip settings

  4. Once you're inside the paneHolder timeline, choose Edit

    The paneHolder clip settings
  5. Create a new layer named actions, and place it at the top of the layer stack. Select frame 1 of the actions layer, and open the Actions panel (F9, or Option+F9 on Mac). Add the code shown in Listing 36.5.

    This code creates a new XML instance named xmlData. The gallery instance (already placed on the Stage) is typed as a Gallery class member. The host variable should be set to the domain name of your Web server. Do not use the localhost value unless you are testing against a Web server running on your computer.

    Note

    When you're ready to deploy the final version of the Flash movie, you can set host to an empty string, or the folder path leading to the PHP script files. Also, if you have difficulties testing against your own PHP server, you can use http://www.flashsupport.com/fb/as2/gallery/ as the value for the host variable to test your Flash movie.

    The init() function uses the Proxy.create() method to delegate the onLoad() handler of the xmlData instance to the onFileData() function. When the XML data has loaded from the PHP script, the onFileData() function invokes. The host value is appended to the files.php?dir=images/ string in the load() method of the xmlData instance.

    The onFileData() function cycles through the returned XML data, which resembles that shown in Listing 36.1. The for() loop goes through each <img> node (xn) and maps each attribute to a property of the same name on an object (item) that is passed to the items array. After each <img> node has been processed, the items array is used for the items property of the Gallery instance, gallery.

    The rootURL, thumbScript, and thumbHeight properties of the Gallery instance are also set in the onFileData() function. Once these properties have been set, the load() function is invoked, starting the process of loading the thumbnail images.

    Example 36.5. Loading the XML Data

    import ascb.util.Proxy;
    
    var xmlData:XML = new XML();
    var gallery:com.themakers.Portfolio.Gallery;
    var host:String = "http://localhost/";
    
    init();
    
    function init():Void {
       xmlData.ignoreWhite = true;
       xmlData.onLoad = Proxy.create(this, onFileData);
       xmlData.load(host + "files.php?dir=images/");
    }
    
    function onFileData(success:Boolean):Void {
       trace("onFileData > " + success);
       var files:Array = xmlData.firstChild.childNodes;
       var items:Array = new Array();
       for(var i:Number = 0; i < files.length; i++){
          var xn:XMLNode = files[i];
    var item:Object = {
             src: xn.attributes.src,
             width: Number(xn.attributes.width),
             height: Number(xn.attributes.height),
             caption: xn.attributes.caption,
             filename: xn.attributes.filename
          };
          items.push(item);
       }
       gallery.items = items;
       gallery.rootURL = host;
       gallery.thumbScript = "resize.php";
       gallery.thumbHeight = 50;
       gallery.load();
    }
  6. Save the main_starter.fla document, and test the movie (Ctrl+Enter or

    Loading the XML Data
The basic thumbnails loading into the Gallery component

Figure 36.6. The basic thumbnails loading into the Gallery component

Note

You can find this version of the main_starter.fla file as main_101.fla in the ch36/in_process folder on this book's CD-ROM.

Phase 3: Displaying the Full-size JPEG Image

Because the XML data provided by the files.php script completely describes each JPEG image in the chosen Web folder, your work with the main_starter.fla document is finished. You complete the remaining changes within the Gallery class file.

Loading the full-size image

After you have the thumbnail JPEG images loading from the resize.php script, you're ready to add more functionality to each MovieClip instance containing a JPEG thumbnail. The mc instance created in the for() loop of the buildHolders() function is the primary instance to target for adding button behaviors.

You also need to track which thumbnail is currently selected. Just as the List component has a selectedIndex property indicating which entry in the list is active, the Gallery component needs a selectedIndex property to indicate which thumbnail has been clicked by the user.

  1. Go back to the Gallery.as file, and add the bold code shown in Listing 36.5. This code has the following changes:

    • buildHolders: This function now creates an onRelease() handler for each mc instance holding a JPEG thumbnail image. The onRelease() handler is delegated to the onThumbClick() function of the Gallery class. A reference to the mc instance is passed to the Proxy.create() method in order for the onThumbClick() handler to identify which thumbnail image has been clicked. Also, the first mc instance to be created in the for() loop is set as the value of a new private variable named _thumb. This variable can be referenced in later functions to also identify which mc instance was clicked last.

    • onThumbClick: This function is invoked whenever the user clicks a thumbnail image in the ScrollPane instance. When a thumbnail is clicked, the _thumb variable is set to the passed mc reference of the function. Then, the selectedIndex property is set to that clip's idx value. Remember, the for() loop of the buildHolder() function assigns an idx value to each thumbnail mc instance. The idx value matches the index of the corresponding JPEG data in the items array.

    • loadImage: This function does the work of changing the contentPath property of the Loader instance, _clo, to the full-size JPEG image URL. The selectedIndex value is used to look up the JPEG file data from the items array. The src property, as built by the script in Listing 36.6, contains the URL to the JPEG image. This value is appended to the rootURL value and then set as the new contentPath property value. The loadImage() function, by design, is only invoked by the selectedIndex setter function.

    • selectedIndex: This pair of setter/getter functions creates a new property named selectedIndex. This property tracks which index of the items array is currently selected. Whenever the user clicks a thumbnail button, the selectedIndex value is updated and the loadImage() function is invoked.

    Example 36.6. Tracking the Active Thumbnail

    import ascb.util.Proxy;
    import flash.display.BitmapData;
    import flash.filters.*;
    import flash.net.FileReference;
    import mx.transitions.Tween;
    import com.themakers.Effects.EasyFilter;
    
    class com.themakers.Portfolio.Gallery extends MovieClip {
    
       private var _csp:mx.containers.ScrollPane;
       private var _clo:mx.controls.Loader;
       private var _tCaption:TextField;
       private var _data:Array;
       private var _rootURL:String;
       private var _thumbScript:String;
       private var _thumbHeight:Number;
       private var _thumbSpacing:Number;
       private var _mcl:MovieClipLoader;
       private var _imgColl:MovieClip;
       private var _thumb:MovieClip;
       private var _selectedIndex:Number;
    
       function Gallery(){
          init();
       }
    
       private function init():Void {
          [No changes to this function]
       }
    
       private function onLoad():Void {
          [No changes to this function]
       }
    
       private function stylePane():Void {
          [No changes to this function]
       }
    
       private function buildHolders():Void {
          var holder:MovieClip =  _scrollPane.content;
          _mcl = new MovieClipLoader();
          _mcl.addListener(this);
          var files:Array = items;
          var w:Number = 0;
          var coll:MovieClip = _imgColl = holder.createEmptyMovieClip(
                                                               "_imgColl",
                                                               1
                                                             );
          for(var i:Number = 0; i < files.length; i++){
             var item:Object = files[i];
             var mc:MovieClip =  coll.createEmptyMovieClip(
                                                    "image_" + i,
                                                    i+1
                                                   );
             mc._x = (i == 0) ? 0 : coll["image_" + (i-1)]._x + 
    Tracking the Active Thumbnail
    calcThumbW(files[i-1]) + _thumbSpacing;
    var disp:MovieClip = mc.createEmptyMovieClip("disp", 1);
             var imgH:MovieClip = disp.createEmptyMovieClip("imgH", 1);
             var img:MovieClip = imgH.createEmptyMovieClip("img", 1);
             if(i == 0) _thumb = mc;
             mc.idx = i;
             mc.onRelease = Proxy.create(this, onThumbClick, mc);
             var path:String = thumbURL + escape(item.src);
             _mcl.loadClip(path, img);
          }
       }
    
       private function calcThumbW(oFile:Object):Number {
          [No changes to this function]
       }
    
       private function onThumbClick(mc:MovieClip):Void {
          _thumb = mc;
          selectedIndex = mc.idx;
    
    }
    
           private function loadImage():Void {
           var idx:Number = selectedIndex;
           var item:Object = items[idx];
           _loader.contentPath = rootURL + item.src;
              }
       public function load():Void {
          [No changes to this function]
       }
    
       public function set selectedIndex(idx:Number):Void {
          if(_selectedIndex != idx){
             _selectedIndex = idx;
            loadImage();
    
          }
       public function get selectedIndex():Number {
          return _selectedIndex;
       }
       [Other public properties have been omitted from this listing]
    }
  2. Save the Gallery.as file.

  3. Go back to the main_starter.fla document, and test it (Ctrl+Enter or

    Tracking the Active Thumbnail
The full-size JPEG image for the first thumbnail

Figure 36.7. The full-size JPEG image for the first thumbnail

Updating the scroll bar and auto-loading the first image

As Figures 36.6 and 36.7 illustrate, the scroll bar of the nested ScrollPane instance (_scrollPane) is not visible as more thumbnails load into the instance. The ScrollPane instance needs to be told when to redraw its UI elements— the ScrollPane component does not automatically detect when more content has been added beyond its visible frame.

  1. Go to the Gallery.as file, and add the functions shown in Listing 36.7. Place these functions after the last private function, loadImage, and before the public functions. This code contains two new functions:

    • onLoadInit: This function is an event listener for the MovieClipLoader instance, _mcl, created in the buildHolders() function. Whenever a thumbnail image has finished loading, the onLoadInit() function is automatically invoked by the _mcl instance. A reference to the MovieClip holder for the image is passed to the function, where the idx value assigned to the outer mc holder for the nested thumbnail holder is accessed. When the first thumbnail in the ScrollPane instance loads, the selectedIndex property is set to 0, which invokes all of the code in the public function set selectedIndex() area of the class file. This process sets the loading of the first full-size JPEG image into action. If the very last thumbnail is loaded into the ScrollPane instance, the updateScroller() function is invoked.

      Tip

      You can place the updateScroller() action in the onLoadInit() handler outside of the if/else statement to force the ScrollPane instance to update after every thumbnail load. If you have several images in your Web folder, you might wait a long time before the last thumbnail loads.

    • updateScroller: This function fires one action: _scrollPane.redraw(true);. This action forces the ScrollPane instance to re-examine its contents and determine if a vertical and/or horizontal scroll bar is necessary.

      Note

      The Listing36-7.as file in the ch36 folder of this book's CD-ROM shows the new code within the entire Gallery class file.

      Example 36.7. The onLoadInit() and updateScroller() Functions

      private function onLoadInit(mc:MovieClip):Void {
         var idx:Number = mc._parent._parent._parent.idx;
         if(idx == 0){
            selectedIndex = 0;
         } else if(idx == items.length - 1){
            updateScroller();
         }
      }
      
      private function updateScroller():Void {
         _scrollPane.redraw(true);
      }
  2. Save the Gallery.as file.

  3. Go back to the main_starter.fla document and test it (Ctrl+Enter or

    The onLoadInit() and updateScroller() Functions
The updated ScrollPane instance

Figure 36.8. The updated ScrollPane instance

Phase 4: Enhancing the Thumbnail and Image States

Right now, you have a Gallery component that can load clickable thumbnails that load full-size JPEG images. While this functionality is critical to the success of the Gallery component, the same functionality could be accomplished in a regular HTML page with less effort. Let's add some features that are truly within the domain of Flash technology.

Framing the selected thumbnail with the BevelFilter class

In this section, you learn how to add a bevel filter to the selected thumbnail image.

  1. Go back to the Gallery.as file. Add the code shown in Listing 36.8. Note that the public function set selectedIndex should already be defined in your code— add the new code shown in bold. This code adds two new functions, and extends the functionality of the selectedIndex setter function:

    • frameThumb: This function creates a new BevelFilter instance named bf for the selected thumbnail, which is retrieved from the _imgColl holder within the ScrollPane instance. (_imgColl is set in the buildHolders() function.) The bf instance is assigned to the filters array of the selected thumbnail, and the alpha of the clip is set to 100%.

      Tip

      We use the default values of the BevelFilter class. If you search the Flash CS3 Help panel for "BevelFilter class," you can find more information on changing the look and feel of the filter with the thumbnail images, using BevelFilter properties such as distance and angle.

    • dimThumb: This function retrieves the previously selected thumbnail, removes any filters, and sets the alpha of the previous thumbnail to 75%.

    • selectedIndex: The setter function for the selectedIndex property now invokes the dimThumb() function with the existing _selectedIndex value before a new _selectedIndex value is assigned. After a new value has been assigned, the frameThumb() function is invoked. Remember, the selectedIndex property is the heart of the Gallery class— any change to the selectedIndex value propagates to other functions within the class.

    Note

    The Listing36-8.as file in the ch36 folder of this book's CD-ROM shows the new code within the entire Gallery class file.

    Example 36.8. Framing the Selected Thumbnail

    private function frameThumb():Void {
       var mc:MovieClip = _imgColl["image_" + selectedIndex];
       var bf:BevelFilter = new BevelFilter();
       mc.filters = [bf];
       mc._alpha = 100;
    }
    
    private function dimThumb(idx:Number):Void {
       var mc:MovieClip = _imgColl["image_" + idx];
    mc.filters = [];
       mc._alpha = 75;
    }
    
    public function set selectedIndex(idx:Number):Void {
       if(_selectedIndex != idx){
          if(_selectedIndex != undefined) dimThumb(_selectedIndex);
          _selectedIndex = idx;
          frameThumb();
          loadImage();
       }
    }
  2. Save the Gallery.as file.

  3. Go back to the main_starter.fla document, and test it (Ctrl+Enter or

    Framing the Selected Thumbnail
The BevelFilter applied to the thumbnail image

Figure 36.9. The BevelFilter applied to the thumbnail image

Creating a loading transition with the BitmapData and BlurFilter classes

Let's continue the fun with Flash filters! In this section, you learn how to use the BitmapData class to make a copy of the thumbnail image over the Loader component area. The thumbnail, of course, is not as large as the full-size JPEG image. As such, the thumbnail image is stretched and pixilated when it's set to the same width and height of the full-size image. You use the BlurFilter class to smooth the thumbnail's pixilation. The filter's strength is inversely proportional to the loaded percent of the full-size JPEG image. As the full-size JPEG image loads into the Loader component, the intensity of the BlurFilter instance is gradually diminished.

  1. Go back to the Gallery.as file and add the bold code shown in Listing 36.9. This code modifies existing functions and adds a few new ones:

    • init: This function uses two new private variables: _blurStrength indicates the maximum blur applied to the copied thumbnail when the copy is made, and _overlay is a new MovieClip instance that holds the copied thumbnail in the overlayThumb() function. The position of the _overlay instance is set to the same X and Y position as the _clo instance.

    • onLoad: This handler is modified to add two event listeners to the Loader component, _loader. The "progress" event is broadcasted from the Loader component as new bytes of a loaded full-size JPEG image arrive into the Flash movie. This event is captured by the onImgProgress() function. The "complete" event is broadcasted by the Loader component when the full-size JPEG image has fully loaded into the Flash movie. This event is captured by the onImgComplete() function.

    • overlayThumb: This function creates a bitmap copy of the selected thumbnail, scales the copy to fit within the dimensions of the Loader component, and sets the initial blur of the scaled copy to a maximum intensity. The overlayThumb() function is invoked by the selectedIndex property when a new thumbnail is clicked. Here, the new BitmapData class is used to create the copy of the loaded thumbnail JPEG image. The new bitmap is attached to a new MovieClip holder named _bitmap within the _overlay instance. The _overlay instance is then resized using the same procedure that the Loader component uses to fit loaded images within its display area.

    • blurOverlay: This function creates the BlurFilter instance responsible for blurring the copied thumbnail image. The function requires one parameter: the percent loaded of the full-size JPEG image. If the loading process has just started, the percent loaded is equal to 0. This value is remapped to a blur intensity value (blurVal), as indicated by the _blurStrength variable set in the init() function. As more bytes of the JPEG image load into the movie, the blurVal amount is reduced. The BlurFilter instance is applied to the filters array of the _overlay instance.

    • onImgProgress: This handler is invoked whenever the Loader component broadcasts a "progress" event. When this event occurs, the loaded percent of the JPEG is retrieved with the percentLoaded property of the Loader component and passed to the blurOverlay() function.

    • onImgComplete: When the Loader component broadcasts the "complete" event, the onImgComplete() function is invoked. The "complete" event signals that the full-size JPEG image has loaded completely into the Flash movie. At this point, the _bitmap instance within the _overlay instance can be removed to reveal the full-size JPEG below it.

    • selectedIndex: The overlayThumb() function is added to the setter function for the selectedIndex property. Whenever the user clicks a new thumbnail image, the process of copying, scaling, and blurring the thumbnail is started.

    Note

    The Listing36-9.as file in the ch36 folder of this book's CD-ROM shows the new code within the entire Gallery class file.

    Example 36.9. Copying and Blurring the Thumbnail Image

    private var _blurStrength:Number;
    private var _overlay:MovieClip;
    
    private function init():Void {
       _thumbSpacing = 1;
       _blurStrength = 20;
       _overlay = createEmptyMovieClip("_overlay", 10);
       _overlay._x = _loader._x;
       _overlay._y = _loader._y;
    }
    
    private function onLoad():Void {
       stylePane();
       _loader.addEventListener("progress", Proxy.create(this, ;
         onImgProgress));
       _loader.addEventListener("complete", Proxy.create(this, ;
         onImgComplete));
    }
    
    private function overlayThumb():Void {
       var mc:MovieClip = _thumb;
       var w:Number = mc._width;
       var h:Number = mc._height;
       var bmd:BitmapData = new BitmapData(w, h);
       bmd.draw(mc);
       var holder:MovieClip = _overlay.createEmptyMovieClip("_bitmap", 1);
       holder.attachBitmap(bmd, 1);
       var lw:Number = _loader.width;
       var lh:Number = _loader.height;
       var factor:Number = h >= w ? lh/h : lw/w;
       _overlay._xscale = _overlay._yscale = factor*100;
       _overlay._x = _loader._x + ((_loader.width - _overlay._width)/2);
       _overlay._y = _loader._y + ((_loader.height - _overlay._height)/2);
       blurOverlay(0);
    }
    
    private function blurOverlay(pl:Number):Void {
       var n:Number = (pl*(_blurStrength/10))/10;
       var blurVal:Number = _blurStrength - n;
       var bf:BlurFilter = new BlurFilter(blurVal, blurVal, 3);
       _overlay.filters = [bf];
    }
    
    private function onImgProgress(e:Object):Void {
       var loader:mx.controls.Loader = e.target;
       blurOverlay(loader.percentLoaded);
    }
    
    private function onImgComplete(e:Object):Void {
       _overlay._bitmap.removeMovieClip();
    }
    
    public function set selectedIndex(nIdx:Number):Void {
       if(_selectedIndex != nIdx){
          if(_selectedIndex != undefined) dimThumb(_selectedIndex);
          _selectedIndex = nIdx;
          overlayThumb();
          frameThumb();
          loadImage();
       }
    }
  2. Save the Gallery.as file.

  3. Go back to the main_starter.fla document, and test it (Ctrl+Enter, or

    Copying and Blurring the Thumbnail Image
The blurred copy of the thumbnail image

Figure 36.10. The blurred copy of the thumbnail image

Transitioning thumbnail states with the Tween and ColorMatrixFilter classes

The thumbnails in the ScrollPane component can also use a scripted tween to fade to a desaturated state as the user views each full-size image. In this section, you see how the Tween class can programmatically update the thumbnail images. You can create a Tween instance by using the following syntax:

import mx.transitions.Tween;
var mc:MovieClip;
var tw:Tween = new Tween(mc, "_x", mx.transitions.easing.Regular.easeOut, 
Transitioning thumbnail states with the Tween and ColorMatrixFilter classes
mc._x, mc._x + 100, 5, true);

The Tween constructor accepts seven arguments, in the following order:

  • target: The first argument specifies the object whose property will be manipulated by the Tween instance. You can pass any object reference you want, including a TextField, MovieClip, or Object reference.

  • property name: The second argument indicates which property of the target object will be updated by the Tween instance. This argument should be a String value. For example, to control a MovieClip instance's X position, pass a value of "_x" as the second argument.

  • easing class: The third argument specifies the type of tween you'd like to use. You can use a variety of easing classes. If you do not require any special type of easing with the tween, you can specify a null value.

  • starting value: The fourth argument indicates the starting value that the Tween instance should use. You can use any numeric value, such as the current X position or alpha value of a MovieClip instance.

  • ending value: The fifth argument specifies the finish value for the Tween instance. You can use any numeric value. When the Tween instance reaches this value, the onMotionFinished handler for any listener assigned to the Tween instance is invoked.

  • duration: The sixth argument indicates how long the tween should last. This numeric value can be specified as seconds or frames.

  • time unit: The seventh and final argument determines the unit of measure for the duration argument, as a Boolean value. If you pass true as the last argument, the unit of measure is seconds. If you pass false, the unit of measure is frames.

  1. Go back to the Gallery.as file and add the code shown in Listing 36.10. This code replaces the existing dimThumb() function with a new set of actions to utilize the Tween class.

    • dimThumb: This function is invoked from the selectedIndex property, just as it was in earlier sections of this project. Two new Tween instances are created for the thumbnail instance. The first Tween instance named twSaturation is responsible for modifying the saturation value of the thumbnail instance. The Regular.easeOut static class is specified as the easing class for both Tween instances. The starting value for the saturation tween is 0 (no change) and the ending value is −100 (color removed, desaturated). The duration of both tweens is one second. The twAlpha instance animates the current alpha of the thumbnail instance to the muted 75% used earlier. The thumbnail instance is added as a listener to both Tween instances; therefore, the onMotionFinished() handler of the thumbnail instance is fired when the tweens finish. The onTweenFinish() function of the Gallery class is delegated for this handler. Because saturation values are not a directly accessible value to use with the Tween class, a new property named thumbSaturation is created for the thumbnail instance. The watch() method can detect any changes to this property on the instance, and the Proxy.create() method is specified as the event handler for the watch() method.

    • onThumbSaturation: This function is invoked whenever the saturation tween (twSaturation) updates the thumbSaturation property of the thumbnail instance. Here, the new value created by the tween is passed to the EasyFilter.saturate() method to create a new ColorMatrixFilter instance. We discuss the EasyFilter.saturate() method in greater detail at the start of this chapter.

    • onTweenFinish: This handler is invoked by each Tween instance when the respective tween has completed. Each tween is removed from a tweens array stored within the thumbnail instance.

    • controlTweens, clearTweens: These functions manage the playback of the Tween instances. You add more functions later in this chapter that take advantage of these functions.

    Note

    The Listing36-10.as file in the ch36 folder of this book's CD-ROM shows the new code within the entire Gallery class file.

    Example 36.10. Tweening the Thumbnail States

    private function dimThumb(idx:Number):Void {
       var mc:MovieClip = _imgColl["image_" + idx];
       if(mc.tweens != undefined) clearTweens(mc);
       var twSaturation:Tween = new Tween(mc, "thumbSaturation", 
    Tweening the Thumbnail States
    mx.transitions.easing.Regular.easeOut, 0, −100, 1, true); var twAlpha:Tween = new Tween(mc, "_alpha",
    Tweening the Thumbnail States
    mx.transitions.easing.Regular.easeOut, mc._alpha, 75, 1, true); twSaturation.addListener(mc); twAlpha.addListener(mc); mc.tweens = [twSaturation, twAlpha]; mc.watch("thumbSaturation", Proxy.create(this, onThumbSaturation), mc ); mc.onMotionFinished = Proxy.create(this, onTweenFinish, mc); } private function onThumbSaturation(prop:String, oldVal:Number,
    Tweening the Thumbnail States
    newVal:Number, mc:MovieClip):Void { mc.filters = [EasyFilter.saturate(newVal)]; updateAfterEvent(); } private function onTweenFinish(tw:Tween, mc:MovieClip):Void { for(var i:Number = 0; i < mc.tweens.length; i++){ if(mc.tweens[i] == tw) mc.tweens.splice(i, 1); } if(mc.tweens.length < 1) delete mc.tweens; } private function controlTweens(mc:MovieClip, action:String):Void { for(var i:Number = 0; i < mc.tweens.length; i++){ mc.tweens[i][action](); }
    }
    
    private function clearTweens(mc:MovieClip):Void {
       controlTweens(mc, "stop");
       delete mc.tweens;
    }
  2. Save the Gallery.as file.

  3. Go back to the main_starter.fla document, and test it (Ctrl+Enter or

    Tweening the Thumbnail States

Setting the image caption

After you have the full-size JPEG image loading into the Loader component, you're ready to populate the _captionField TextField instance, which you copied into the Gallery symbol earlier in this chapter. The JPEG files provided in the starter files and finished files folders have had metadata added to them. The caption metadata is read by the JPEG-Meta.php script on the server and inserted into the XML data sent to the Flash movie with the files.php script.

  1. Go back to the Gallery.as file and add the bold code shown in Listing 36.11. Add the new private variable to the list of existing private variables at the top of the class file, modify the existing init() and loadImage() functions, and add the new displayCaption() function below the last private function in the class file.

    • init: The new _captionSpacing variable stores the gap, in pixels, that should buffer the top of the _captionField instance and the bottom of the full-size JPEG image.

    • loadImage: After the full-size JPEG image starts to load into the Loader component, the displayCaption() function is invoked to show the image's caption. The caption text is stored in the caption property of the current object within the items array, as described by the XML document delivered by the files.php script.

    • displayCaption: This function populates the _captionField instance with the new caption text and positions the field below the lower-left corner of the image.

    Note

    The Listing36-11.as file in the ch36 folder of this book's CD-ROM shows the new code within the entire Gallery class file.

    Example 36.11. The displayCaption() Function

    private var _captionSpacing:Number;
    
    private function init():Void {
       _thumbSpacing = 1;
       _blurStrength = 20;
       _captionSpacing = 5;
    _overlay = createEmptyMovieClip("_overlay", 10);
       _overlay._x = _clo._x;
       _overlay._y = _clo._y;
    }
    
    private function loadImage():Void {
       var idx:Number = selectedIndex;
       var item:Object = items[idx];
       _loader.contentPath = rootURL + item.src;
       displayCaption(item.caption);
    }
    
    private function displayCaption(val:String):Void {
       _captionField.text = val;
       _captionField._x = _overlay._x;
       _captionField._y = _overlay._y + _overlay._height + _captionSpacing;
    }
  2. Save the Gallery.as file.

  3. Return to the main_starter.fla document, and test it (Ctrl+Enter or

    The displayCaption() Function
The caption text below the JPEG image

Figure 36.11. The caption text below the JPEG image

Completing the thumbnail button handlers

The thumbnail functionality is nearly complete. In its current state, the thumbnail images, once clicked, remain muted— even when the user rolls over a previously selected thumbnail. In this section, you add onRollOver and onRollOut handlers to each thumbnail instance.

  1. Go back to the Gallery.as file, and add the bold code shown in Listing 36.12.

    • buildHolders: This function, which creates the original thumbnail holders, is modified to assign onRollOver and onRollOut handlers to each thumbnail instance (mc). The Proxy.create() method delegates these handlers to the onThumbOver and onThumbOut functions of the Gallery class.

    • onThumbOver: This handler checks to see if any tweens are active on the thumbnail when the rollover event occurs. If there are any active tweens, they are paused. Any active filters applied to the instance are stored in a new property named existingProps. This property is used in onThumbOut to restore the last state of the button. Any filters on the thumbnail instance are removed, and the alpha is set to 100%. Note that these actions are only applied to a thumbnail instance if it is not the active thumbnail.

    • onThumbOut: This handler resumes any active tweens that may have been in progress when the user rolled over the thumbnail instance. Any filters that were applied to the instance before the rollover event occurred are also reapplied to the clip.

    • selectedIndex: When a thumbnail is initially selected with the selectedIndex property, the existingProps property is initialized with the filters that are applied to the selected thumbnail.

    Example 36.12. The onRollOver() and onRollOut() Thumbnail Handlers

    private function buildHolders():Void {
       var holder:MovieClip =  _scrollPane.content;
       _mcl = new MovieClipLoader();
       _mcl.addListener(this);
       var files:Array = items;
       var w:Number = 0;
       var coll:MovieClip = _imgColl = holder.createEmptyMovieClip(
                                                            "_imgColl",
                                                            1
                                                          );
       for(var i:Number = 0; i < files.length; i++){
          var item:Object = files[i];
          var mc:MovieClip =  coll.createEmptyMovieClip(
                                                 "image_" + i,
                                                 i+1
                                                );
          mc._x = (i == 0) ? 0 : coll["image_" + (i-1)]._x + 
    The onRollOver() and onRollOut() Thumbnail Handlers
    calcThumbW(files[i-1]) + _thumbSpacing; var disp:MovieClip = mc.createEmptyMovieClip("disp", 1); var imgH:MovieClip = disp.createEmptyMovieClip("imgH", 1); var img:MovieClip = imgH.createEmptyMovieClip("img", 1); if(i == 0) _thumb = mc;
    mc.idx = i;
          mc.onRelease = Proxy.create(this, onThumbClick, mc);
          mc.onRollOver = Proxy.create(this, onThumbOver, mc);
          mc.onRollOut = Proxy.create(this, onThumbOut, mc);
          var path:String = thumbURL + escape(item.src);
          _mcl.loadClip(path, img);
       }
    }
     private function onThumbOver(mc:MovieClip):Void {
        if(mc != _thumb){
           if(mc.tweens.length > 0) controlTweens(mc, "stop");
           var existingFilters:Array = new Array();
           for(var i:Number = 0; i < mc.filters.length; i++){
               existingFilters.push(mc.filters[i]);
           }
           mc.existingProps = { filters: existingFilters, alpha: mc._alpha};
           mc.filters = [];
           mc._alpha = 100;
       }
    }
    private function onThumbOut(mc:MovieClip):Void {
       if(mc.tweens.length > 0 && _thumb != mc){
             controlTweens(mc, "resume");
       } else {
          mc.filters = mc.existingProps.filters;
          mc._alpha = mc.existingProps.alpha;
       }
    }
    public function set selectedIndex(nIdx:Number):Void {
       if(_selectedIndex != nIdx){
          if(_selectedIndex != undefined) dimThumb(_selectedIndex);
          _selectedIndex = nIdx;
          overlayThumb();
          frameThumb();
          loadImage();
             _thumb.existingProps = {
             filters: _thumb.filters,
             alpha: _thumb._alpha
          };
       }
    }
  2. Save the Gallery.as file.

  3. Return to the main_starter.fla file, and test it (Ctrl+Enter or

    The onRollOver() and onRollOut() Thumbnail Handlers

Building a right-click download menu item for the full-size JPEG

To enable the user to download the full-size JPEG image, you use the ContextMenu class to add a new menu item to the Flash Player's contextual menu that appears when the user right-clicks (or Control+clicks on Mac) the Loader component display area.

  1. Go back to the Gallery.as file, and add the bold code shown in Listing 35.13. This code creates or modifies the following functions:

    • onLoad: This handler, which is invoked automatically when the Gallery instance loads in the Flash movie, now invokes the addContextMenu() function.

    • addContextMenu: This function creates a new instance of the ContextMenu class. The built-in items of the Flash Player contextual menu (such as Zoom In, Zoom Out, and so on) are disabled for this new menu. A new custom menu item is created, named "Download this image." When the user selects this menu item, the downloadImage() function is invoked. The new menu is then assigned to the Loader component, _clo.

    • downloadImage: This function uses the new Flash Player 8 FileReference API to enable the user to download a file from the Web server. The current JPEG file URL and JPEG filename values are retrieved from the items array, and passed to the download() method of the fileRef instance.

    Example 36.13. Utilizing the FileReference API

    private function onLoad():Void {
       stylePane();
       addContextMenu();
       _loader.addEventListener("progress", Proxy.create(this, 
    Utilizing the FileReference API
    onImgProgress)); _loader.addEventListener("complete", Proxy.create(this,
    Utilizing the FileReference API
    onImgComplete)); } private function addContextMenu():Void { var cm:ContextMenu = new ContextMenu(); cm.hideBuiltInItems(); cm.customItems.push(new ContextMenuItem("Download this image",
    Utilizing the FileReference API
    Proxy.create(this, downloadImage))); _loader.menu = cm; } private function downloadImage():Void { var fileRef:FileReference = new FileReference(); var item:Object = items[selectedIndex]; var path:String = rootURL + item.src; if(!fileRef.download(path, item.filename)) { trace("dialog box failed to open."); } }
  2. Save the Gallery.as file.

  3. Go back to the main_starter.fla document, and test it (Ctrl+Enter or

    Utilizing the FileReference API
The new right-click menu item

Figure 36.12. The new right-click menu item

Phase 5: Finalizing the Component

You've completed all of the scripting for the Gallery component— Congratulations! You can now deploy Flash movies with the Gallery component. In this last section, you learn how to enable inspectable properties of the Gallery class to display in the Parameters tab of the Property inspector (or Component Inspector panel).

Adding the component definition

If you open the Library panel of the main_starter.fla document, you can see that the symbol type of the Gallery symbol is a Movie Clip. In order to convert the component to a full-fledged component (complete with component icon!), you need to specify the Gallery class in the Component Definition dialog box.

  1. With the main_starter.fla document active, open the Library panel (Ctrl+L or

    Adding the component definition
  2. Right-click (or Control+click on Mac) the Gallery clip, and choose Component Definition.

  3. In the Component Definition dialog box, type com.themakers.Portfolio.Gallery in the AS 2.0 Class field, as shown in Figure 36.13. Select the Require minimum player version check box, and choose Flash Player 8. Click OK. Select the Require minimum ActionScript version, and choose ActionScript 2.0.

    The Component Definition dialog box

    Figure 36.13. The Component Definition dialog box

  4. To see the inspectable parameters, you can repeat Step 2 to see the parameters automatically created for you by Flash CS3, as shown in Figure 36.14.

    The updated Component Definition dialog box

    Figure 36.14. The updated Component Definition dialog box

  5. To see the new parameters, select the gallery instance of the Gallery component on the Stage and open the Property inspector. When you select the Parameters tab, you should see the new inspectable parameters as shown in Figure 36.15.

The Parameters tab for the Gallery component

Figure 36.15. The Parameters tab for the Gallery component

Now, you can change the thumbnail height, server host, and thumbnail script values directly in the Property inspector.

Note

You still need to specify an items value for the Gallery instance in ActionScript code, and invoke the load() handler to initiate the thumbnail loading process.

Changing script paths for final deployment

When you're ready to deploy a Flash movie featuring the Gallery component, keep in mind that you may very likely need to change to the values used in the frame 1 script to initiate loading of the XML data from the files.php script. Make sure you specify a valid Web folder name (or path) as the dir value appended to the files.php filename in the XML.load() handler. You may also need to update the name and path to the resize.php script in the onFileData() handler written within the frame 1 script.

Note

We'd like to know what you think about this chapter. Visit www.flashsupport.com/feedback to send us your comments.

Summary

  • The process for planning a Flash component can require ample time to properly spec the functionality you want to build.

  • The Gallery component can load thumbnail versions of JPEG images on your Web server and display the full-size JPEG image when the thumbnail is clicked.

  • Server-side scripting can enable a wide range of functionality within your Flash movies. For the Gallery component, the PHP script files provide XML data and dynamically resized JPEG images to the Flash movie.

  • The JPEG-Meta.php script written by Rob Williams can retrieve JPEG metadata within your own PHP scripts.

  • The Proxy class written by Joey Lott can delegate events and additional parameters within your ActionScript 2.0 classes.

  • The BitmapData class can create a copy of a MovieClip surface. You can use this class to replicate graphics within your Flash movies.

  • The Flash Player 8 filters can add more visual effects to interactive button states.

  • You can use the FileReference API to download and upload files, without relying on the browser to intervene.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.23.63.252