Tutorials Books Videos Forums

Change the theme! Search!
Rambo ftw!

Customize Theme


Color

Background


Done

Adding Thumbnails

by kirupa   | filed under Flash and ActionScript

This is an archived tutorial from the kirupa.com legacy collection. It covers software that may no longer be available, but it is kept online because the ideas still hold up.

A popular tutorial on this site is the Photo Gallery using XML and Flash tutorial. As time went on, the forums were filled with requests to make modifications to the tutorial. In this tutorial, I will address several of the more common requests I noticed. The modifications I explain in this tutorial are:

The following is an example of the modified photo gallery tutorial:

[ use your arrow keys or press the Next and Previous buttons ]

 NOTE
This tutorial is a modification over the original Photo Gallery tutorial. If you have not finished that, you may be a bit lost in this tutorial, for I will not be repeating concepts already covered in the previous tutorial

Thumbnails

Let's first discuss how we are going to approach implementing thumbnails into Flash.

The obvious first step, is to procure the smaller images that will make up our thumbnails. Ideally, you would want your thumbnail images to be considerably smaller than your main images. If your images are too large, it defeats the purpose of having a quick-loading preview of all the images.

Next, we need to find a way of displaying our thumbnails. There are two popular ways you can choose to display thumbnails: the grid and scroller.

The grid is where all of the thumbnail images are displayed in, surprise surprise!, a grid:

[ the grid ]

The scroller, similar to what you see in the above animation, is the method where you scroll through a row of images:

[ the scroller ]

I prefer the scroller simply because the thumbnail images I'm using are a bit too large to efficiently fit in a small area. Because I am going to be using a scroller, I need to figure out an efficient way of scrolling the images and stopping the scrolling if there are no images left to be scrolled or your mouse cursor is not over the thumbnail area.

Finally, and most importantly, the thumbnail data will need to be taken from an XML file. That means we need to make our thumbnail code expandable so that, even if you use some images that are oddly sized, your photo gallery adapts to it nicely. We don't want to mess with our FLA a whole lot!

Now that we have a better idea of how to approach the thumbnails, let's start creating them in Flash. Onwards to the next section!



If you arrived here without having read the previous section, please go back to the previous section to get filled up on what to expect on this page!

The XML File

Since our thumbnail graphics will be loaded from an XML file, we need to modify our XML data to incorporate the thumbnails. In our original photo gallery, the XML file had the following structure:

					<pic>

  <image>Path

  to Image</image>

  <caption>Image

  Caption</caption>

  </pic>

  <pic>

  <image>Path

  to Image</image>

  <caption>Image

  Caption</caption>

  </pic>

Let's modify the structure by adding a node for thumbnails:

					<pic>

  <image>Path to Image</image>

  <caption>Image Caption</caption>

  <thumbnail>Path

  to Thumbnail</thumbnail>

  </pic>

  <pic>

  <image>Path to Image</image>

  <caption>Image Caption</caption>

  <thumbnail>Path

  to Thumbnail</thumbnail>

  </pic>

For the sake of simplicity, I have already created the thumbnail images and uploaded them for you to use. In your folder containing all of your photo gallery files, create a new file called images.xml with the following information:

The above XML data is very similar to the file you already have seen from the photo gallery, but it includes some extra children for thumbnails.


Now, I have provided a sample FLA for you to download and use. Click the following link to download it:

The Flash File

From the zip file you downloaded above, extract the FLA to the same location as your images.xml file, and then open the file thumbnail_initial.fla. You will notice that this FLA is very similar if you have used the photo gallery tutorial. In fact, it is the exact same FLA with the exception of the extra space below the text fields:

If you were to test your animation right now, provided images.xml is in the same directory as the FLA, you will see a functioning version of the photo gallery you had worked on earlier.

So, let's extend this photo gallery with thumbnails. The next section will get you started!



Make sure you have your FLA opened and ready. Let's start the modifications:

  1. Select the first frame of your Actions layer and press F9 or go to Window | Development Panels | Actions.
  2. You should already see a lot of code from our original photo gallery. The following text area contains the code that I would like you to use.
     
    A lot of the code is the same, so you can either modify your existing code by adding in just the colored code, or you can simply overwrite all of your code with what I have in the following scroll area by copying and pasting everything contained in the text area below:
     
  3. Once you have copied and pasted the above code from Step 2 into your loadXML function, you can close your Actions window for now.

    Now, we need an empty movie clip that will load our thumbnail images. Go to Insert | New Symbol. From the Create New Symbol window, enter the name thumbnailMC, select the option for Movie Clip, and press OK.
  4. You should now be in the timeline for the thumbnailMC movie clip you created in the previous step. Click the Scene 1 tab to return back to your main timeline:

[ click the Scene 1 tab ]

  1. You should be back at your main timeline with the familiar photo gallery layout. Create a new layer and call it thumbnail. Select this layer in order to keep it in focus.
  2. Press Ctrl + L or go to Window | Library to access your Library. Find the symbol called 'thumbnailMC" (which you created earlier) and drag and drop it on the large empty portion of your stage above the previous and next buttons:

[ drag and drop the thumbnailMC symbol from the library to your stage ]

  1. Select your thumbnailMC symbol, which should simply be the default hollow circle symbolizing an empty object, and make sure its X position is on 22, and its Y position is on 289. The area near your thumbnailMC movie clip should look like the following image:

[ where your empty thumbnailMC movie clip will be - x: 22, y: 289 ]

  1. No, we still aren't finished with our thumbnailMC movie clip! Select that movie clip again, look towards the bottom left of your Properties panel, and give it the instance name: thumbnail_mc.
  2. If you press Ctrl + Enter now, you will see all of our thumbnails loading in the same spot. We don't want that, of course, but we also aren't done with the tutorial...yet!

    Let's specify the left and right boundaries of our thumbnail gallery. First, draw a vertical rectangle with width 15, height 90, and an x position of 10 and a y position of 280:

[ draw a vertical rectangle to help specify the boundaries of your movie ]

  1. Select the rectangle you drew, and convert that to a symbol by pressing F8 or by going to Modify | Convert to Symbol. Make sure to select the option for Movie Clip and call it boundary from the Convert to Symbol window that appears.
  2. Once you have converted your rectangle (boundary movie clip) into a symbol, create a copy of your boundary movie clip and paste it on the right side to make a right boundary.

    If you are unfamiliar with copying/pasting, select your boundary movie clip, right click on the movie clip, select copy, right click on an empty area of your stage, select paste, and then move your copied version of the boundary movie clip to the right side of your photo gallery as shown in the following picture:

[ the boundary clip and its copy on the right ]

  1. You now have two movie clips, the boundary movie clips, that make up the left and right boundary of our thumbnail animation. But, we haven't given them both instance names! Select the left boundary movie clip and give it the instance name: hit_left. Give the right boundary movie clip the name hit_right.
  2. Preview the tutorial now by pressing Ctrl + Enter. You should see a line of thumbnails, and you can also use your mouse to scroll the thumbnails around. But, notice that the images are seen beyond their boundaries:

[ notice how the images appear beyond the boundaries ]

  1. Go back to the Flash timeline, and insert a layer above your thumbnail layer. Give your new layer any name you want. Now, draw a rectangle that stretches from the left boundary to the right boundary:

[ insert a layer above your thumbnail layer and draw a large rectangle ]

  1. You may have guessed at what I'm trying to do. I'm creating a mask! Right click on the layer that you drew your rectangle on (the layer above your thumbnail layer) and select 'Mask'.
  2. Finally, select both your left and right boundary movie clips. From the Properties Panel, click the Color drop-down menu, select Alpha, and drag the slider down to 0%.

[ select both the boundary movie clips and set their alphas to 0 ]

  1. You are now done with the photo gallery! Preview the file in your window, and you should see a nice, thumbnail scroller for selecting your thumbnail images.

While you have gotten your thumbnails to display, we haven't reached the most important part of this tutorial - the part where I explain what part the 17 or so steps and the code have in order to create this cool and useful effect.

So, let's head on to the next section!



You just survived a painstaking page of getting the thumbnails to work from the previous section, but how did all of those various steps combine into getting our thumbnails to work? Hopefully, this page will answer that and more!

First, let's take a look at out the movie clips and shapes we added for our photo gallery modification. The following image (color/opacity added for emphasis) provides details on the symbols I will be discussing:

As you recall from the first page, the thumbnails were constrained by boundaries on both the left and right sides. Those boundaries are determined, not by the hit_left and hit_right, but primarily by the mask rectangle shape colored blue in the above image.

Note that the thumbnails are all loaded into the thumbnailMC movie clip, masking the movie clip with the giant rectangle ensured that the contents of thumbnailMC, the thumbnail images, would not be visible unless they were within the boundaries of the mask rectangle.

So, what role do hit_left and hit_right play? They tell Flash where the boundaries are for determining whether the row of thumbnails have actually reached their left or right boundaries. While the mask rectangle ensured that you only saw thumbnails within the boundary specified by the mask, the hit_left and hit_right movie clips help Flash to make sure that you don't overscroll in either the left or right directions. The scrolling should stop when the last thumbnail crosses the hit_right movieclip or when the first thumbnail is to the left of the hit_left movie clip.

I can't elaborate more on the function of hit_left and hit_right without taking look at the code. Most of the code should be familiar to you from the photo gallery tutorial, so I'll only elaborate on the code that is new to what we are doing now.

Let's take a look at the first section code:

function loadXML(loaded) {
  if (loaded) {
  xmlNode = this.firstChild;
  image = [];
  description = [];
  thumbnails = [];
  total = xmlNode.childNodes.length;
  for (i=0; i<total; i++) {
  image[i] = xmlNode.childNodes[i].childNodes[0].firstChild.nodeValue;
  description[i] = xmlNode.childNodes[i].childNodes[1].firstChild.nodeValue;
  thumbnails[i] = xmlNode.childNodes[i].childNodes[2].firstChild.nodeValue;
  thumbnails_fn(i);
  }
  firstImage();
  } else {
  content = "file not loaded!";
  }
}

In the above section of code, the data from the XML file is formatted and stored in various arrays. You can see how that is done in great detail here: http://www.kirupa.com/developer/mx2004/xml_flash_photogallery4.htm


thumbnails = [];

In this line of code, I am initializing a new variable called thumbnails that will act as an array.


thumbnails[i] = xmlNode.childNodes[i].childNodes[2].firstChild.nodeValue;
thumbnails_fn(i);

The above two lines (three if count the break caused by the formatting) are contained in the for loop that goes through each line of your XML file and assigns that data to the appropriate variables.

The thumbnail data is the third element in the i-th node. Recall that the numbering for positions in an XML file starts at 0, so the third element would be represented by a 2 - hence, childNodes[2].

Each thumbnail element is itself a child of a larger node, and that node is accessed by childNodes[i], and i is a variable that runs between 0 and the total number of nodes in our XML file. All of that data, is stored in our thumbnails array which we initialized just a few lines ago!

Finally, I make a call to a function called thumbnails_fn. I also pass the variable i to the thumbnails_fn function. Let's talk about the thumbnails_fn function in the next section!



The code in the previous section was just a setup to the real code that is, coincidentally, on this page. Let's take a look at the thumbnails_fn function that I briefly mentioned towards the end of the previous section:

Before I go over each line of the code, let me briefly summarize what this function does. This function takes in a number, k, as an argument from the loadXML function. This number determines which image is being loaded, and this function is only active while the for loop in the loadXML function is still looping.

In that brief period of time, this function creates a new movie clip for each new value of k that is passed to it, and each new movie clip acts as a holder for each thumbnail image. After each image is loaded, we then give it the onRollOver and onRelease properties so that people can click on each image and have it's larger counterpart be loaded in the top frame.

Let's dissect this code:

thumbnail_mc.createEmptyMovieClip("t"+k, thumbnail_mc.getNextHighestDepth());

I am creating a new empty movieclip called ("t"+k), inside the movie clip thumbnail_mc. In order to do that, I'm using the createEmptyMovieClip function that takes in the arguments for instance name and depth provided I call the function from the target movie clip: thumbnail_mc.

For example, movie clips created will be called t0, t1, t2,...., tn where n is the value for k. Speaking of k, it is the value that is passed to the thumbnails_fn function from the loadXML function. More specifically, k is similar to the variable p that is used throughout the photo gallery code.

Notice also that I don't give an arbitrary value for the depth, but instead use the getNextHighestDepth() function to ensure that each movie clip created into thumbnail_mc has a different depth.


tlistener = new Object();

This line is fairly straightforward. I simply declare the tlistener variable as an object. No tricky alternative meanings here.....I hope!


image_mcl = new MovieClipLoader();
image_mcl.addListener(tlistener);
image_mcl.loadClip(thumbnails[k], "thumbnail_mc.t"+k);

Let's jump a number of lines down and look at the last three lines. This and the above tlistener definition are part of the functioning for the MovieClipLoader() class that I assign to the variable image_mcl.

Instead of explaining this, Macromedia's documentation for the MovieClipLoader along with loadClip does a brilliant job of explaining this. They even provide a good example. Therefore, I will skip explaining the technical functioning of this function.

Before I leave, take note that thumbnail[k] references the thumbnail array, and combined with the index position k, returns the path to the image that needs to be loaded. The same path that we earlier defined in our XML file.


tlistener.onLoadInit = function(target_mc) {

If you recall, tlistener is the variable that I declared as an object earlier. Under the MovieClipLoader class, tlistener is used to gauge the progress of the loaded images, and if the image has both loaded AND initialized, any code contained here is executed.

One last feature is that this function takes in the argument target_mc, which is passed to it from the loadClip method: "thumbnail_mc.t"+k, of course, k is replaced with a number referencing the index position of your array.


target_mc._x = hit_left._x+(target_mc._width+5)*k;

This line is responsible for placing each thumbnail in the row format. Surprisingly, all of the above produces a simple number - the x position of a particular thumbnail.

hit_left._x returns the x position of the hit_left movie clip. This produces an offset so that your thumbnails don't load at the very left-most boundary of your movie. You could simply use a number such as 10 or 20 to produce the necessary offset, but if you were to vary your thumbnail gallery beyond what I created, then you'll have to go back and change the numbers manually. In this case, simply moving the hit_left movieclip to accommodate a different photo gallery will automatically adjust the positioning of the thumbnails also.

(target_mc._width+5)*k is the line that positions each thumbnail relative to the preceding thumbnail. I offset the position of each future thumbnail by the width of the current thumbnail. The value of k places each thumbnail far away so that you don't overlap an existing thumbnail. The value, 5, is simply the spacing between each thumbnail, so you have a small gap between each image.


target_mc.pictureValue = k;

I am assigning the value k to a variable pictureValue in our target_mc movie clip. Remember that target_mc varies depending on the value of k in the loadClip action. This is a very effective way of assigning a variable to a movieclip that you can easily access later without worrying about variable scope and other fun issues that I won't address at this time!


target_mc.onRelease = function() {
  p = this.pictureValue-1;
  nextImage();
};
target_mc.onRollOver = function() {
  this._alpha = 50;
  thumbNailScroller();
};
target_mc.onRollOut = function() {
  this._alpha = 100;
};

In these series of lines, I give each thumbnail the ability to execute some code when clicked on or rolled over/out.

The code for onRelease is similar to pressing the Previous and Next buttons in the photo gallery. The only difference is that the number p varies, for you may skip over a few images when clicking on an image to load after all. So, we need to determine the value of p for each image. Luckily, if you remember, I assigned each movie clip the value of k in the pictureValue variable, and k is the variable p in disguise for this function!

For the onRollOver action, I set the alpha of the thumbnail to 50. There is no real reason behind me doing that besides informing the users that rolling over the thumbnail does something similar to a button. I also call the thumbNailScroller() function, and you will learn more about that later.

When you roll out of the thumbnail, I return the alpha of the movie clip back to 100. I'm trying to simulate the Over and Default states of a button with this movie clip.


Alright, we are almost done. Let's now take a look at our thumbNailScroller_fn function that moves the thumbnails left and right depending on where your mouse cursor is. Onwards to the next section!



The code in the previous section was just a setup to the real code that is, coincidentally, on this page. Let's take a look at the thumbnails_fn function that I briefly mentioned towards the end of the previous section:

Before going through the code line-by-line, let me explain what this function does. The thumbNailScroller function, as its name implies, helps scroll the thumbnails when the mouse moves over the left or right boundaries. Most of the above code lies in determining when to start and stop the scrolling:


this.createEmptyMovieClip("tscroller", 1000);

I'm creating a new, empty movie clip called tscroller at a depth of 1000.

scroll_speed = 10;

The variable scroll_speed controls  how fast all of the thumbnails scroll left or right.

tscroller.onEnterFrame = function() {

I'm specifying the onEnterFrame of the newly created tscroller movie clip. If you recall, onEnterFrame executes any code contained within it repeatedly unless you explicitly delete the onEnterFrame.

if ((_root._ymouse>=thumbnail_mc._y) && (_root._ymouse<=thumbnail_mc._y+thumbnail_mc._height)) {

The above if condition checks to make sure that the thumbnail scroller works only when our mouse is contained within the vertical (y) constraints of the thumbnail_mc movie clip.

The following diagram shows the constraint imposed by _root._ymouse >= thumbnail_mc._y. Anything beyond the top border of the thumbnail is fair game:

But, I also include an extra constraint to make sure that the thumbnails don't scroll when your mouse is below the thumbnail such as the Previous and Next buttons. That is fixed by the _root._ymouse<=thumbnail_mc._y+thumbnail_mc._height code.

Thumbnail_mc._y gives the numerical value of the top border of your thumbnails, and thumbnail_mc._height gives you the total height of your thumbnails. The total y position then, is the sum of both the y position of the top thumbnail border and the total thumbnail height.

Each of the above two constraints by themselves are not very practical. But, both of them combined with the && operator produces just the right vertical boundary I need, as seen by the combination of the blue and yellow rectangles as the green rectangle shown below:

The next course of action would be to limit the horizontal range of movement. You wouldn't want to have the thumbnails scroll when your mouse cursor is well to the left or right of the actual photo gallery area!

The right boundary of our horizontal scrolling is determined by:

(_root._xmouse>=(hit_right._x-40)) && (thumbnail_mc.hitTest(hit_right))

I check for two things. First, I check to see if the mouse cursor is 40 pixels to the left of the right-most boundary of our hit_right movie clip.

Second, I make sure that the thumbnail_mc movie clip is hitting hit_right. Even though, due to the mask, it looks as if all of the thumbnails are neatly contained within the viewing area, in reality, the thumbnails extend well towards the right-end of the screen provided there are enough images.

The hitTest makes sure that the thumbnail_mc still is hitting the hit_right movie clip. In other words, it makes sure there are still images left for us to scroll. I wouldn't want you to keep scrolling indefinitely after all of the thumbnails have left the viewing area!

The complement of this is the boundary for the left side of our thumbnail scroller:

(_root._xmouse<=(hit_left._x+40)) && (thumbnail_mc.hitTest(hit_left))

I do the same thing as I did for the right boundary, except I change a few signs and movie clip references. Like before, I check to make sure that the mouse is within a reasonable area on the left side before the scrolling is invoked, and I also make sure that there are images left to scroll by using the hitTest function.

thumbnail_mc._x -= scroll_speed;

If both the vertical and horizontal right boundary conditions are met, that means we are interested in scrolling our images to the left. Therefore, I have the code set to move thumbnail_mc in the horizontal direction at a speed determined by the scroll_speed variable.

thumbnail_mc._x += scroll_speed;

Likewise, if both the vertical and horizontal left boundary conditions are met, I scroll the thumbnail_mc movie clip to the right at the speed determined by scroll_speed.

if ((_root._ymouse>=thumbnail_mc._y) && (_root._ymouse<=thumbnail_mc._y+thumbnail_mc._height)) {
  if ((_root._xmouse>=(hit_right._x-40)) && (thumbnail_mc.hitTest(hit_right))) {
  thumbnail_mc._x -= scroll_speed;
  } else if ((_root._xmouse<=(hit_left._x+40)) && (thumbnail_mc.hitTest(hit_left))) {
  thumbnail_mc._x += scroll_speed;
  }
} else {
  delete tscroller.onEnterFrame;
}

The structure of this if statement is something that I have not used in any of my tutorials before. It is an if - else if form. Normally, there would be an if statement and an else statement, but I wanted to have one extra condition for executing code.

This is a nicer way of combining to if statements together, and you would suffer no loss in functionality if you decided to use two if statements instead.

delete tscroller.onEnterFrame;

I check to see if the mouse cursor is within the vertical area of the thumbnail, and if the mouse cursor is not there, that means that the user has scrolled and moved his/her mouse cursor away from the scrolling area.

Since having onEnterFrame loop continuously can be taxing on the CPU, it is good to delete them. Since our thumbNailScroller() function is called each time you hover over a thumbnail, a new empty 'tscroller' movie clip is created with a new onEnterFrame also being initiated. In other words, the deletion is only in effect until you call the thumbNailScroller() function again.

In the next section, I will do a lightning round summary of the six pages you've clobbered through already!



I will now provide a quick summary of everything in our thumbnail code, from the previous sections, and what causes it to work.

First, you decide that you want to have thumbnails. You make the necessary modifications to the XML file by adding in the path for your thumbnail images. Now that you have your XML file modified, your next course of action is to modify the loadXML function in your FLA. You tell Flash to loop through each node and pick out the thumbnail image path and store it in an array.

So, now, you have reached a point where data from XML has been retrieved, processed, and stored as an array in Flash. What do you do with an array full of thumbnail image paths? You create an empty movie clip for each thumbnail and load that thumbnail into it!

Loading the thumbnail is only one part of our whole thumbnail scroller. You have to make sure that each image is spaced accordingly by taking into account each image's width and not loading the next successive image on top of a previous image! That is where our hit_left and hit_right movie clips first gain importance.

The second part of the thumbnail scroller is to actually scroll when our mouse is on the left or right edges of our thumbnail. In this tutorial, I used the two movie clips, hit_left and hit_right to simulate the left and right boundaries of our thumbnail scroller. If the mouse was both within the thumbnail area and touching either the left or right hit movie clips, your thumbnails will scroll provided there are thumbnails left to scroll.

Since most of the code is based on the existing photo gallery code, it was not difficult to load the larger image when a thumbnail is clicked. Each thumbnail contained a number that was equivalent to a number used in loading images in the photo gallery. Passing that number to our existing functions from our photo gallery was all it took to getting images to load.

I have provided a ZIP file containing both our final thumbnail FLA and the modified images.xml file.

A great big thanks go out to all of the members who constantly helped others with their thumbnail and photo gallery questions on the forums. I'm sure there are more members, but the ones I've seen helping answer these questions often are scotty, stringy, senocular, lostinbeta, claudio, and more!



Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence, ads, and algorithm-driven doodads. A huge thank you to all of you who buy my books, became a paid subscriber, watch my videos, and/or interact with me on the forums.

Your support keeps this site going! 😇

Kirupa's signature!

The KIRUPA Newsletter

Thought provoking content that lives at the intersection of design 🎨, development 🤖, and business 💰 - delivered weekly to over a bazillion subscribers!

SUBSCRIBE NOW

Creating engaging and entertaining content for designers and developers since 1998.

Follow:

Popular

Loose Ends

:: Copyright KIRUPA 2026 //--