Get Adobe Flash player

WordBubble Tutorial

The WordBubble class is a fairly simple class that pops up a WordBubble that you can use for a variety of things such as a tool tip. This class is also designed to be a jumping off point to create other types of pop-ups. When should you write a class? Basically, anytime I find myself copying and pasting the same code from one project to another, I think, aha!, this would make a good class. And then, in the future all I have to do is set up a line or two of code in my present project instead of copying and pasting everything over and over. The advantage to setting up your own class library is that when you make additions or changes to a particular class you only have to do it once and every project you use that class in gets the benefit the next time you recompile, or republish, it. If you add additional parameters to the constructor function you will have to change the code in the projects that are affected, but this is far simpler than updating functions and adding in new variables to each project individually. If you don't use a class library, I urge you to take a few minutes and set one up. It makes life a lot easier.

A Word About Class Packages and Class Libraries

If you are new to Classes, you may be a bit mystified by the Class Package structure. At the top of each Class you will see something like this:

    package ca.xty.myUtils {

And in the code where you import classes into your project you will have something like this:

    import ca.xty.myUtils.WordBubble;{

What this is telling you is that the WordBubble.as Class in lives a folder called myUtils. The myUtils folder lives in another folder called xty. The xty folder lives in another folder called ca. This is a conventional way to organize your classes. What you call your folders is up to you. People tend to use their domains since that guarantees you a unique path. To take full advantage of the Flash IDE, we can set it up to automatically include your class library. First, you need to make another folder to hold all these other folders. I call my folder flashClasses. Where you put the flashClasses folder on your computer doesn't really matter, but mine lives in the main folder where I keep all my flash projects. So, set up the flashClasses folder and then open up Flash. In CS4, go to Edit-> Preferences-> ActionScript. Down near the bottom, click on ActionScript 3.0 Settings. Near the top, you'll see a space labeled Source Path. Click the + sign to add a new path. Now click the folder icon to browse to the flashClasses folder you just made and click OK. Now Flash will include the flashClasses folder, and all it's contents, in any of your movies. So, when you use import ca.xty.myUtils.WordBubble;, the path to the ca folder is assumed. This procedure makes it easy to organize your classes, and find them when you need them.

The alternative to the above procedure is to simply drop the ca folder into the same folder as your .fla, but if you are going to be serious about using Classes, it is worth the initial effort to get things set up properly. Now, let's get going by having a look at what this class does.

What you need

Download the wordBubble.zip file and let's dig into the code and see how this works.

The Demo Files

Open up the wordBubble.zip and you will see a bunch of files and folders. The wordBubbleTest.fla is the fla that runs the demonstration we want to look at first. There is nothing on the stage, but you will find some items in the library and you'll see that the Document Class is set to WBDemo. The WBDemo.as class is commented to give you an idea of how this is set up. If you take a look at it, you see that we have set up a variable called wb as an instance of our WordBubble class. In this example we will be using the ROLL_OVER and ROLL_OUT event listeners to call the WordBubble. Have a look in the overHandler function and you'll see how little it takes to set this class in motion.

    wb = new WordBubble(150, 25, 0x000000, 0xff0000, 0x980101, "This is Button 1 and it uses the timer feature.", 2);
    setWBXY();

We use our variable wb to create a new instance of WordBubble and pass the class several parameters.
1) width of the WordBubble
2) height of the WordBubble
3) text color
4 & 5) the colors of the background gradient
6) the text we want to display
7) an optional parameter that sets up a timer function to automatically make the WordBubble disappear, after 2 seconds in this case.

The setWBXY() function is responsible for handling the positioning of the WordBubble on the stage.

private function setWBXY():void{
    wb.x = mouseX - (wb.width/2);
    if(wb.x < 5){
        wb.x = 5;
    }
    if((wb.x + wb.width) > stage.stageWidth){
        wb.x = (stage.stageWidth - wb.width) - 5;
    }
    wb.y = mouseY - (wb.height + 5);
    if(wb.y < 0){
        wb.y = mouseY + 5;
    }
    addChild(wb);
}

We use the mouseX and mouseY properties, then subtract half the width of the WordBubble to approximately center it. Next we make sure that it remains on stage by correcting it's position if necessary. Once everything is set up properly, the WordBubble is added to the display list.

Now let's take a look at the WordBubble.as class and see how it operates.

From the Top

Open up the WordBubble.as file. At the very top is a bunch of commented out stuff. These are the functions you would need to add to your Document Class if you were using this in a ROLL_OVER / ROLL_OUT capacity. There are just there to help you remember how to use this class 6 months from now.

Next we have the package declaration:

    package ca.xty.myUtils

If you have your own class library set up, change this to reflect the new location of the WordBubble.as file. Remember to also change the import statement in the WBDemo.as file. Now we import all the classes we require to make this class work. It uses the Caurina Tweener classes, which I have included in the zip file. You can substitute your favorite Tween engine if you want to.

Next up we define the variables we'll be using in this class. My convention is to use an underscore to mark the variables we get from the passed parameters.

private var _wbWidth:int;
private var _wbHeight:int;
private var _txtColor:Number;
private var _bgColor1:Number;
private var _bgColor2:Number;
private var _wbText:String;
private var _wbInterval:int;

private var wbTF:TextField;

private var wbFormat:TextFormat;

private var xPos:int;
private var yPos:int;

private var popUpPanel:Sprite;

private var timer:Timer;

Once we have the _wbInterval we check to see whether it is equal to zero, and, if it's not, then we multiply it by 1000 because Flash timers use milliseconds.

public function WordBubble(wdth:int, hght:int, txtColor:Number, bgColor1:Number, bgColor2:Number, wbText:String, wbInt:int = 0):void{
    _wbWidth = wdth;
    _wbHeight = hght;
    _txtColor = txtColor;
    _bgColor1 = bgColor1;
    _bgColor2 = bgColor2;
    _wbText = wbText;
    _wbInterval = wbInt;
    if(_wbInterval != 0){
        _wbInterval *= 1000;
    }

Next we set up our text format for the text we will be showing.

wbFormat = new TextFormat();
wbFormat.font = "Verdana";
wbFormat.size = 11;
wbFormat.color = _txtColor;
wbFormat.align = "center";

Now we create a new Sprite called popUpPanel. This will be the container that holds all of the elements that make up the WordBubble. This makes life simple for a few of reasons:
1) when we want to get rid of the WordBubble all we have to do is removeChild(popUpPanel)
2) It makes it easy to line things up using the popUpPanel as the reference point. We start at the coordinates 0,0 and build everything from there. We are not worried about how this will look on stage since it is the instance of the WordBubble,wb, that we will be positioning on the stage.
3) We now have one object to tween.
Because we are going to tween the WordBubble, we set the initial value of alpha to 0.

popUpPanel = new Sprite();
addChild(popUpPanel);
popUpPanel.alpha = 0;

Now we initialize our first Shape and add it to the popUpPanel and set it's x and y to 0,0. Remember, these coordinates are those of the popUpPanel.

var bg1:Shape = new Shape();
bg1.x = 0;
bg1.y = 0;
popUpPanel.addChild(bg1);

Variable bg1 is going to be a gradient filled rounded rectangle. The _bgColor1 and _bgColor2 variables are put to use here, as are the _wbWidth and _wbHeight.

var fillType:String = GradientType.LINEAR;
var colors:Array = [_bgColor1, _bgColor2];
var alphas:Array = [1, 1];
var ratios:Array = [0, 255];
var matrix:Matrix = new Matrix();
var gradWidth:Number = _wbWidth;
var gradHeight:Number = _wbHeight;
var gradRotation:Number = 90 / 180 * Math.PI;
var gradOffsetX:Number = 0;
var gradOffsetY:Number = 0;

matrix.createGradientBox(gradWidth, gradHeight, gradRotation, gradOffsetX, gradOffsetY);
var spreadMethod:String = SpreadMethod.PAD;
bg1.graphics.beginGradientFill(fillType, colors, alphas, ratios, matrix, spreadMethod);
bg1.graphics.drawRoundRect(0, 0, _wbWidth, _wbHeight, 12);
bg1.graphics.endFill();

Now we draw a second rounded rectangle on top of the first one. The second one, bgW, is 6 pixels smaller in both the height and the width. It is also positioned at the coordinates 3, 3. This gives us the illusion of a 3 pixel border around the second rounded rectangle bgW. Here the colors for the gradient are fixed, but you could easily add them as parameters and set them on the fly.

var bgW:Shape = new Shape();
bgW.x = 3;
bgW.y = 3;
popUpPanel.addChild(bgW);

var fillTypeW:String = GradientType.LINEAR;
var colorsW:Array = [0xffffff, 0xeeeeee];
var alphasW:Array = [1, 1];
var ratiosW:Array = [0, 255];
var matrixW:Matrix = new Matrix();
var gradWidthW:Number = gradWidth - 6;
var gradHeightW:Number = gradHeight - 6;;
var gradRotationW:Number = 90 / 180 * Math.PI;
var gradOffsetXW:Number = 0;
var gradOffsetYW:Number = 0;

matrixW.createGradientBox(gradWidthW, gradHeightW, gradRotationW, gradOffsetXW, gradOffsetYW);
var spreadMethodW:String = SpreadMethod.PAD;
bgW.graphics.beginGradientFill(fillTypeW, colorsW, alphasW, ratiosW, matrixW, spreadMethodW);
bgW.graphics.drawRoundRect(0, 0, gradWidthW, gradHeightW, 12);
bgW.graphics.endFill();

Now that our background is all set up, let's add out text field. To give us a bit of padding, we set the x and y coordinates to be 3 less than the second rounded rectangle's (bgW) x and y. Then, when we declare the width and height we make it 6 pixels less than the width and height of bgW. Because we can't be certain how much text will be passed, we set the text field's autoSize property to LEFT and set multiline and wordWrap to true. This combination will force the text field to expand down if it requires more room.

wbTF = new TextField();
wbTF.x = bgW.x + 3;
wbTF.y = bgW.y + 6;
wbTF.width = bgW.width - 6;
wbTF.height = bgW.height - 6;
wbTF.autoSize = TextFieldAutoSize.LEFT;
wbTF.multiline = true;
wbTF.wordWrap = true;
wbTF.htmlText = wbText;
wbTF.setTextFormat(wbFormat);
popUpPanel.addChild(wbTF);

Once the text field wbTF is in place we check it's height against the height of the first rounded rectangle, bg1. If the height of bg1 minus the wbTF is less than our top and bottom margin - a total of 12 - then we need to make the background bigger.

if(bg1.height - wbTF.height < 12){
    bg1.height = wbTF.height + 12;
    bgW.height = bg1.height - 6;
    wbTF.y = bg1.y + 6;
}

Before we bring the WordBubble to life, we need to check once more and see what the value of _wbInterval is. If it is not equal to 0, then we want to use the timer feature and so we use the first Tween statement, which includes an onComplete function - startTimer - which, of course, starts our timer. If _wbInterval is in fact equal to 0, then we use the second Tween statement and pop the WordBubble into life.

if(_wbInterval != 0){
    Tweener.addTween(popUpPanel, {alpha:1, time:1, delay:.1, transition:"easeOutExpo", onComplete:startTimer});
}else{
    Tweener.addTween(popUpPanel, {alpha:1, time:1, delay:.1, transition:"easeOutExpo"});
}

The next function starts our timer using the interval we set via the constructor and calls the next function, onTimerComplete, where we fade out the WordBubble, remove the event listener for the timer and then head to our last function, removeWB, which - you may have guessed - removes the WordBubble by getting rid of the popUpPanel.

private function onTimerComplete(event:TimerEvent):void{
    Tweener.addTween(popUpPanel, {alpha:0, time:1, transition:"easeOutExpo", onComplete:removeWB});
    timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
}

private function removeWB():void{
    removeChild(popUpPanel);
}

And that's all of it. Let's recap what you need to do to make this work with any project on Page 2.

Page 2