Home Labs Galleries PetitOn

Building a Flickr Flash Display, Part 2

Resources: Kelvin Luck's flashr library, the fla file and the ActionScript for this tutorial.

Next: Part 3, Tweening and Automation

In the first part of this installment, I walked you through building a Flickr Service client, using Kelvin Luck's flashr library. This library acts as a wrapper for the Flickr API. We made some simple modifications to Kelvin's ActionScript application, to create something like the Flickr Badge. Most of the work in that first part was done to deconstruct and change the HTML embedding code, separating the structure, the styling and the logic. Finally we arrived at a fairly simple and XHTML standards compliant embedding element.

The display itself ( development name "petikr badge" ) resemble the Flickr Badge only to it's form, a 3 by 4 matrix of a users recent images delivered from www.flickr.com. The badge so far has no behavior, like the random zooming of images in the original display. It just presents the images.
We added some "chrome"  to the badge by encapsulating it in styled <div> containers and copying a DHTML information widget at the bottom.

There are a lot of things we can do to enhance the petikr badge. First of all we can make it a little more jazzy by adding behavior, making it zoom or switch images. Maybe make it interactive or randomly replace images with new ones from Flickr.

Another thing we may try, is to make the badge more versatile, by making it configurable, so that properties can be set at run time. Examples of properties a user would likely want to tune are, the number of images, the size of the badge, whether zooming should be automatic or manual and what the image selection criteria should be.

In this second part of the tutorial I'll like us to add some behavior to the badge. ( What choice do you have anyway ? ;)

Adding Behavior to the Badge

There are many types of behavior we could add to the badge, but let us start with something simplistic, and interactive. In the original badge, serving as a kind of blueprint for our experiment, the size of the thumbnail images are randomly zoomed one by one to double the size.  I don't really know how the animation is done in the Flickr Badge, as I haven't reverse engineered their Flash Movie.

Here is the meat of the petikr badge, as we left it in the first part of this series. Fetching the recent photos form a person's photo collection at www.flickr.com and laying out in a matrix on the Stage is all done by the AS class MyRecentPhotos. The entrance main() class is called from the first frame of a Flash Move.
The main() function has as the sole responsibility, to create an instance of the class by calling its constructor, where everything that goes on, is initiated. The fetching of images and the layout is delegated to the function omPeopleGetPublicPhotos.

function onPeopleGetPublicPhotos( p:Person ):Void{
	var photosArray:Array = p.getPhotos();
	var userNsid:String = p.nsid;
	for ( var i:Number=0; i<photosArray.length; i++ ){
		var thisPhoto:Photo = Photo(photosArray[i]);
		// create a movieclip to load the photo into
		var mc:MovieClip = _target.createEmptyMovieClip( "photo"+i, i );
		// position the clips so they form a nice grid
		mc._x = (i%3) * 38; // changed i%4 -> i%3
		mc._y = Math.floor(i/3) * 38; // changed i/4 -> i/3
		// create a nested movieclip so that our onPress
		//isn't overwritten by the jpg as it loads
		mc.createEmptyMovieClip("jpgHolder", 1);
		// and load the jpeg into it
		mc.jpgHolder.loadMovie(thisPhoto.thumbnailUrl);
		mc._xscale=mc._yscale=49;
		mc.photo = thisPhoto;
		// add the onPress to this movieclip to link
		// to the relevant photo on flickr.com
		mc.onPress = function(){
			getURL(this["photo"].photoPageUrl, "_blank");
		};
	}
}

When the image thumbnails arrives, the function places each photo in a matrix of MovieClips on the Stage and resizes them to 49% of the original size. Finally it adds an onPress handler to each MovieClip. When the user clicks or presses on an image, a browser window is opened with the users Flickr page for that image.

Adding a Zoom Behavior

What we want to do here, is to add a zooming behavior to each image, so that when the user rolls over an image, it will scale to double its size.

So let's get started already!

First we want to create a new project, so we open the MyRecentPhotos.fla and change the include statement and call to the main() entry point.

// Using the Kelvin API wrapper, zooming onRollOver, onRollOut
import com.petitpub.flickr.MyFlipPhotos;
MyFlipPhotos.main();

We then save the fla file in the project directory, which could be the same as before or a new one. Choosing the same project directory as before, has the advantage that Kelvin's flashr library is already accessible to the Flash authoring tool.

I have changed the name space or path for the MyFlipPhotos ActionScript application to com.petitpub, and so the application must be saved in a <project>/com/petitpub directory under the project directory. So we open the MyRecentPhotos.as file in a plain text editor and save it as MyFlipPhotos.as in the <project>/com/petitpub

Now we are all set, and can add the onRollOver and onRollOut event handlers to each of the MovieClips holding images. We do this in the same manner as the already present onPress handler, i.e. we add the handlers at the end of the onPeopleGetPublicPhotos() function.

First we have to add some global variables

/**
* Variable: xMax
* Max horizontal value for left upper corner of a zoomed image
**/
var xMax = 38;
/**
* Variable: yMax
* Max vertical value for left upper corner of a zoomed image
**/
var yMax = 76;
/**
* Variable: xTemp, yTemp
* Temporary original x, y position values for images
**/
var xTemp:Number;
var yTemp:Number;
/**

The Stage is limited, and when we resize an image from the initial 49% to 100%, we must make sure it stays within the Stage. The image in the left upper corner of the badge has room to expand to the right and downwards and will cover the images below and to the right. The same goes for image number two in the upper row. The third image must be translated one module to the left, not to expand outside the Stage.
The same goes for all images in the rightmost column. Likewise all images in the bottom row must be shifted upwards one module. Otherwise they will expand below the badge. The easiest way to resolve this issue, is to set a maximum value for the x and y position for a zoomed image. The xMax and yMax values represents these constraints.

When the user moves the mouse pointer outside the image, it should resume its original position and size. The xTemp and yTemp variables are used to hold the original position of a zoomed in image.

These class global variables will not be accessible inside the event handler, so we must change their scope by adding the values to each MovieClip holding the images. We do this inside the loop in the  onPeopleGetPublicPhotos() function:

// We have to set this for every mc to access the values from the event handlers
mc.xMax = xMax;
mc.yMax = yMax;

What happens to the image and its neighbors when we zoom an image to double its original size? Obviously the images will overlap, but which one is on top of the other? We don't know this, even if we can calculate it by studying the order in which the MovieClips are added to the Stage. In Flash, even if the MovieClips don't overlap, they will all get their own level or depth or z-value. The z-value may be changed in a number of ways. We can give a MovieClip a new value at any time, or we can swap the depth of one MovieClip with the depth of another. We can also give a clip a new depth by swapping it to an empty level. We can get the first empty level by using the getNextHighestDepth() on the MovieClips parent container. All our image MovieClips are in the _root container ( or Stage ).

var freeDepth=(_root.getNextHighestDepth());

So when a MovieClip is abut to zoom, we can make sure that it stays on top by swapping it to the freeDepth level. When restored to its original size and position, it will stay at that level until another MovieClip is swapped up.

Here are the event handlers.

// add the onRollOver and onRollOut event handlers to zoom the image
mc.onRollOver = function(){
	xTemp=this._x; // Save the original position
	yTemp=this._y;
	this._x = Math.min(xTemp, xMax);
	this._y = Math.min(yTemp, yMax);

	// Swap this mc to first free depth
	this.swapDepths(freeDepth);
	this._xscale=this._yscale=100;
}
mc.onRollOut = function(){
	this._x = xTemp;
	this._y = yTemp;
	this._xscale=this._yscale=49;
}

The onRollOver event handler saves the original position of the image, or rather the MovieClip holding it.
It then moves the image to the left or upwards if they otherwise would extend beyond the boundaries of the badge.
It swaps the current MovieClip to the freeDepth level and scales it to 100%, now covering three other images.

The onRollOut handler restores the MovieClip to it's original position and size.

Notice that the "this" pointer in an event handler always refers to the object that fired the event, in this case the MovieClip sensing the mouse pointer.

Here is the MyFlipPhotos.as Actionscript application, and here is the resulting MyFlipPhotos flickery display badge.

Next: Part 3, Tweening and Automation

Still To Do

Parameterized for user, number of images, matrix.
Tween for image size - automatic ( interval ) or manual ( mouseover )