Caption Class
External ActionScript files (AS files) are normal text files, meaning you can use any text-editor of your choice to create or edit them. Some of you may prefer editing inside of Flash; others may prefer using an external editor (personally I use TextMate 1.5).
Open your text editor and then copy & paste the following code into a new file. Save this file in the base directory as “Caption.as”. I will explain each block of code after I show you the completed class.
import Library;
import mx.transitions.Tween;
import mx.transitions.easing.*;
import flash.filters.DropShadowFilter;
class Caption
{
//Path to the base movieclip containing all required assets.
private var __path:MovieClip;
//Text the caption will display (e.g."Visit Ultrashock.com").
private var __label:String;
//Number of milliseconds before the caption will start fading in.
private var __delay:Number;
//Used to define the interval needed to delay fading in the caption.
private var __interval;
//Prevents caption duplication
private var __virgin:Boolean = true;
//---------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------
//This method is executed everytime an instance of the class is created.
function Caption(label:String,target:MovieClip,delay:Number)
{
//Sets constructor variables to the corresponding class properties.
__path = target;
__label = label;
__delay = delay;
//Assigns value if not specified. This ensures that even if a delay
//is not defined the caption will still be displayed.
delay == undefined ? __delay = 1000 : __delay = delay;
//Begins listening for events
setupEvents();
}
private function setupEvents():Void
{
var mouseListener = {};
//Every time the mouse is moved the eventHandler method is executed.
//This way we will always know exactly where the mouse is positioned.
mouseListener.onMouseMove = Library.delegate(this, "eventHandler");
Mouse.addListener(mouseListener);
positionCaption();
}
private function eventHandler():Void
{
//Checks if the mouse is over the target.
if(__path.hitTest(_root._xmouse, _root._ymouse))
{
if(__virgin)
{
//Prevents this block of code from executing again until
//the mouse is not over the target.
__virgin = false;
//Waits x amount of milliseconds before fading in caption.
__interval = setInterval(this, "drawCaption", __delay);
}
}
else
{
__virgin = true;
//Fixes duplication bugs.
clearInterval(__interval);
//Removes the caption now that the mouse is no longer over the target.
removeMovieClip(__path._parent.alt);
}
}
private function drawCaption():Void
{
//Stops this function executing repeatedly.
clearInterval(__interval);
var altFormat = new TextFormat();
altFormat.font = "arial";
altFormat.size = 10;
//Specifies the base movieclip.
var target = __path._parent;
var shadow = new DropShadowFilter(3, 45, 0x000000, 0.4, 5, 5, 1, 2);
//Creates an empty movieclip for our caption's text field to be drawn into
//and the text field used for the caption.
var alt = target.createEmptyMovieClip("alt", target.getNextHighestDepth());
var label = alt.createTextField("label_txt", 0, 0, 0, 10, 16);
//Changes the size of the text field based on the size of the label text specified.
label.autoSize = "left";
label.multiline = false;
//Makes sure you cannot select the caption's text
label.selectable = false;
label.embedFonts = true;
//Defines a border and background and specifies what color each element will be.
label.border = true;
label.borderColor = 0x000000;
label.background = true;
label.backgroundColor = 0xFDFEC6;
//Sets the text field's text to the label text specified.
label.text = __label;
label.setTextFormat(altFormat);
//Applies the dropshadow
alt.filters = [shadow];
//Initially repositions the caption. Otherwise the caption's position will
//not be corrected until the mouse has been moved.
updatePosition();
//Fades in the caption, making it visible.
var fade = new Tween(alt, "_alpha", None.easeNone, 0, 100, 7);
}
private function positionCaption():Void
{
var mouseListener = {};
mouseListener.onMouseMove = Library.delegate(this, "updatePosition");
Mouse.addListener(mouseListener);
}
private function updatePosition():Void
{
var target = __path._parent;
//Horizontally centers the caption between the mouse.
target.alt._x = target._xmouse-(target.alt._width/2);
//Positions the bottom of the caption at the tip of the mouse.
target.alt._y = target._ymouse-(target.alt._height+5);
}
}
Lets start by looking at the first 4 lines of code:
import Library;
import mx.transitions.Tween;
import mx.transitions.easing.*;
import flash.filters.DropShadowFilter;
Here I import all the external classes needed. This way we don’t have to use a path to the class each time a new instance is created. Class explanations as follows:
- Library – A custom alternative to the Macromedia Delegate utility class. We will be creating this class after we’re finished with this one.
- Tween – Imports the undocumented Macromedia tween class. This is needed to fade the caption in and out smoothly.
- Easing - Supports a total of 16 different kinds of easing (in reality, there are 19, but since 4 are identical, we'll just call it 16). We need this class to add easing when fading the caption.
- DropShadowFilter – This lets you add a drop shadow to a variety of objects in Flash, in this case the caption.
A series of class properties have been defined in the class body. This allows us to have access to them throughout the whole class.
class Caption
{
//Path to the base movieclip containing all required assets.
private var __path:MovieClip;
//Text the caption will display (e.g."Visit Ultrashock.com").
private var __label:String;
//Number of milliseconds before the caption will start fading in.
private var __delay:Number;
//Used to define the interval needed to delay fading in the caption.
private var __interval;
//Prevents caption duplication
private var __virgin:Boolean = true;
At the beginning of this block I’ve defined Caption as a new class; then proceed to define all “class properties” in the class body. Class properties are properties (variables) outside of any class methods, which is why they are defined in the “class body”. Note that you can only set these properties to numbers or strings in the body, once we have created the constructor you can set all other different types of data just as you can a normal property (as long as there isn’t a data type issue).
//---------------------------------------------------------------------------
// Constructor
//---------------------------------------------------------------------------
//This method is executed everytime an instance of the class is created.
function Caption(label:String,target:MovieClip,delay:Number)
{
//Sets constructor variables to the corresponding class properties.
__path = target;
__label = label;
__delay = delay;
//Assigns value if not specified. This ensures that even if a delay
//is not defined the caption will still be displayed.
delay == undefined ? __delay = 1000 : __delay = delay;
//Begins listening for events
setupEvents();
}
This is the class’s constructor method. A constructor is a method that is executed only once every time a new instance of the class is created. Remember when you were making the Flash file and I told you how the Caption class has 3 parameters? This is where they are passed from the Flash file to the class. Once the constructor has been executed I define the class properties that couldn’t be set in the class body since we didn’t have any of the parameters data yet.
private function setupEvents():Void
{
var mouseListener = {};
//Every time the mouse is moved the eventHandler method is executed.
//This way we will always know exactly where the mouse is positioned.
mouseListener.onMouseMove = Library.delegate(this, "eventHandler");
Mouse.addListener(mouseListener);
positionCaption();
}
Sets up a listener to execute the “eventHandler” method each time the mouse is moved. Inside the onMouseMove event I use the Library class’s “delegate” method to fix method scope. Basically this means it allows us to access the class without having any path issues. I will elaborate on this topic after we’ve finished the Caption class.
private function eventHandler():Void
{
//Checks if the mouse is over the target.
if(__path.hitTest(_root._xmouse, _root._ymouse))
{
if(__virgin)
{
//Prevents this block of code from executing again until
//the mouse is not over the target.
__virgin = false;
//Waits x amount of milliseconds before fading in caption.
__interval = setInterval(this, "drawCaption", __delay);
}
}
else
{
__virgin = true;
//Fixes duplication bugs.
clearInterval(__interval);
//Removes the caption now that the mouse is no longer over the target.
removeMovieClip(__path._parent.alt);
}
}
This method does exactly what its name suggests, handles events. What that means is it executes different blocks of code according to the triggered event. In this case it is checking the position of the mouse to know if it should display the caption or remove it.
The next function, “drawCaption” is a bit long so I will be explaining it in bits and pieces.
private function drawCaption():Void
{
//Stops this function executing repeatedly.
clearInterval(__interval);
var altFormat = new TextFormat();
altFormat.font = "arial";
altFormat.size = 10;
//Specifies the base movieclip.
var target = __path._parent;
var shadow = new DropShadowFilter(3, 45, 0x000000, 0.4, 5, 5, 1, 2);
//Creates an empty movieclip for our caption's text field to be drawn into
//and the text field used for the caption.
var alt = target.createEmptyMovieClip("alt", target.getNextHighestDepth());
var label = alt.createTextField("label_txt", 0, 0, 0, 10, 16);
Once the mouse has been placed over the hotspot and the delay time specified has passed while still hovered, this method is executed.
The interval created in the eventHandler method has been cleared to prevent from repeated looping of this method. It’s very important to make sure this line is intact, as you will end up with an endless amount of captions if it is removed.
A new text format that will be applied to the caption text field has been created and 2 of its properties have been set. When you embedded a font in the Flash file and added a linkage ID you were setting it up for the class to use this font for the caption label. If you would like to change the font, go back into the Flash file and update the embedded font as well as it’s linkage ID, then edit the text format’s font property from “arial” to the new linkage ID.
The imported DropShadowFilter class is being used here to setup the drop shadow for the caption. Once the label text field has been created and all it’s properties have been defined we will add this filter to the label’s filter array, which will make the filter visible.
Above the base movieclip (specified in the Flash file) I create the alt movieclip used to hold the caption. The reason I don’t create it inside the base movieclip itself is because the caption will always be repositioning and we are constantly checking if the mouse has been positioned over the hotspot/base movieclip. If the caption is inside the base it will always think the mouse is over the hotspot since it will always be expanding. Therefore the caption would never be removed, even when the mouse is not over the hotspot.
//Changes the size of the text field based on the size of the label text specified.
label.autoSize = "left";
label.multiline = false;
//Makes sure you cannot select the caption's text
label.selectable = false;
label.embedFonts = true;
//Defines a border and background and specifies what color each element will be.
label.border = true;
label.borderColor = 0x000000;
label.background = true;
label.backgroundColor = 0xFDFEC6;
//Sets the text field's text to the label text specified.
label.text = __label;
label.setTextFormat(altFormat);
//Applies the dropshadow
alt.filters = [shadow];
//Initially repositions the caption. Otherwise the caption's position will
//not be corrected until the mouse has been moved.
updatePosition();
//Fades in the caption, making it visible.
var fade = new Tween(alt, "_alpha", None.easeNone, 0, 100, 7);
}
Here I am setting the label text field properties, applying the drop shadow created earlier, positioning everything correctly using the updatePosition function (we will make this method later), and fading in the caption in. Each of these actions has been explained further in the code’s comments.
private function positionCaption():Void
{
var mouseListener = {};
mouseListener.onMouseMove = Library.delegate(this, "updatePosition");
Mouse.addListener(mouseListener);
}
We did this exact same thing with the setupEvents method, except this time it’s executing the updatePosition method. This will insure that the caption is always positioned correctly.
private function updatePosition():Void
{
var target = __path._parent;
//Horizontally centers the caption between the mouse.
target.alt._x = target._xmouse-(target.alt._width/2);
//Positions the bottom of the caption at the tip of the mouse.
target.alt._y = target._ymouse-(target.alt._height+5);
}
Last but not least, this method is used to make the caption follow the mouse. Not only does it follow just above the mouse but also it horizontally centers the caption.

|