Accessibility

Flash Article

 

Tips for migrating your Flash applications to ActionScript 3.0


Dan Carr

Dan Carr

Dan Carr Design

Created:
16 April 2007
Modified:
10 December 2007
User Level:
Intermediate
Products:
Flash

Adobe Flash CS3 Professional includes many great new features, including the ActionScript 3.0 programming language and the ActionScript 3.0 FLA file format. This article is a summary of my notes and reflections as I migrated to using ActionScript 3.0. I also provide solutions that address these topics:

  • Changes to handling movie clips
  • Changes to loading data, content, and symbols
  • Changes to building object classes in ActionScript 3.0

Changes to handling movie clips

The following notes deal with how you handle movie clips:

1. Display objects vs. movie clips

The first thing I noticed in ActionScript 3.0 was the updated MovieClip API. In ActionScript 3.0, the MovieClip API no longer contains the majority of commands I used routinely. I discovered that there is a new model for display objects, where movie clips act as display object containers and keep a list of registered items for easier control. The MovieClip API is now used primarily to traverse a timeline.

In ActionScript 3.0, you use the addChild method to see a display object appear on the Stage. For example, suppose that you want to create an instance of a ComboBox component from the Library. To see the instance appear on the Stage, you would write the following code:

import fl.controls.ComboBox;
 
var myCombo:ComboBox = new ComboBox();
addChild(myCombo);

2. Instance validation

I found some differences in the way instances are handled in ActionScript 3.0 classes. Instances placed on the Stage during authortime automatically associate their instance names with their movie clip container, and the name is available in the ActionScript 3.0 class. Declaring the name in the class as you would in ActionScript 2.0 triggers a compiler error. Inversely, I've noticed the compiler also reports errors when a property is set on an instance that does not exist.

To validate against an undefined instance, use the getChildByName method, as shown in the following code:

var myInstance = getChildByName("instanceNameInQuestion");
if( myInstance!= null )
{
   // Then do something...
}

3. Movie clip (display object) property changes

In ActionScript 3.0, the underscore (_) has been eliminated from the property names. In some cases, the way that values are set for common properties has also been updated.

The alpha property of a movie clip is now set on a scale of 0 to 1 instead of 0 to 100. For example, 50% opacity would be set as follows:

myInstance.alpha = 0.5;

The scaleX and scaleY property of a display object are now set in a similar way. For example, 150% of normal scale would be set as follows:

myInstance.scaleX = 1.5;
myInstance.scaleY = 1.5;

4. this, _root, _parent, and _global

The this alias can be used in ActionScript 3.0 and it behaves as it does in previous versions of ActionScript. The _global path does not exist in ActionScript 3.0. The _parent property can be accessed as the parent property of any display object. The _root path does not exist anymore but using the stage property can produce the same results.

5. Handling depths

I quickly discovered that swapDepths and getNextHighestDepth no longer exist in ActionScript 3.0. Instead you'll use the DisplayObjectContainer methods associated with a movie clip container. The terminology in ActionScript 3.0 is based on the display object's "index" in the list of child objects, instead of the concept of "depth."

To send the myInstance clip to the top of the stacking order, use the following code:

setChildIndex(myInstance, numChildren - 1);

6. Using the Drawing API

As with other changes to the MovieClip API, the dynamic Drawing API has been moved to the graphics property of a display object. Other than its new location, the process for using it is the same—with a few noticeable enhancements.

The code below shows how to dynamically draw a rectangle and then apply the rectangle as a mask to another instance. The mask object has no timeline, so it is created as a sprite instead of a movie clip:

import flash.display.Sprite;
 
// Create mask
var maskArea = new Sprite();
maskArea.graphics.beginFill(0xFF0000);
maskArea.graphics.drawRect(-29.5, -22.5, 59, 46);
addChild(maskArea);
           
// Apply mask
myInstance.mask = maskArea;

Note: When researching common tasks previously associated with the MovieClip object, try looking at the DisplayObject class instead when browsing through the ActionScript 3.0 documentation. For more information on depth control and display object management, see the documentation on the DisplayObjectContainer class in the documentation.

Changes to loading data, content, and symbols

The following notes deal with loading images, server data, symbols, and URLs:

7. Loading images and SWFs

Loading images and SWF files is no longer handled using the loadMovie command or MovieClipLoader class. Instead, use the URLRequest class and the Loader class to accomplish the same task.

The following code shows the barebones of an image loader script:

import flash.display.Loader;
import flash.net.URLRequest;
 
var request:URLRequest = new URLRequest("img/image1.jpg");
var loader:Loader = new Loader();
loader.load(request);
addChild(loader);

8. Loading server data and XML

Using the new ActionScript 3.0 XML capabilities along with the new URLLoader class, I found that working with XML data sources is much easier than before.

The following example illustrates how to load an XML file and then respond to the completion of the data loading process:

import flash.display.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
 
var loader = new URLLoader();
loader.load(new URLRequest("conf/settings.xml"));
 
function onDataHandler(event:Event):void
{
   if((event.target as URLLoader) != null )
   {
      var settingsXML = new XML(loader.data);
   }
}
loader.addEventListener(Event.COMPLETE, onDataHandler);

Note: Notice the use of the as keyword in the event handler function above. In ActionScript 3.0 the as keyword can be used to test whether the data type of one object matches another. It can also be used to cast an object as a related data type. This is handy in cases where you receive a reference to an object but the reference isn't necessarily of the same data type, or in cases where you want to test to see if a data type matches another. For example, in the code above, you can check to see if event.target is a URLLoader by using the as keyword. If the reference is null, it's not a URLLoader. This type of validation is a good way to avoid runtime errors.

9. Loading symbols explicitly

The attachMovie command and linkage identifiers no longer exist in ActionScript 3.0. There are two ways to load symbols from the library. Both routes require that you turn on the Export for ActionScript option in the Linkage properties for the target symbol. Because you can no longer add an identifier, you have to handle everything instead using the class name. If you don't have a custom class for the symbol you want to attach, use the symbol name as inserted by default. In this case, Flash creates a skeleton class for you using the name of the symbol. After the class name is set in the linkage properties, you'll have to determine whether the class name is explicitly known or if it's being dynamically supplied.

When the class name associated with a symbol is explicitly known, the following code pattern is used:

var myInstance = new MyClassName();
addChild(myInstance);

Note: All instances are created using the new keyword in ActionScript 3.0.

10. Loading symbols dynamically

Using the new keyword is easy and a great scripting convention to use, but it only works if you explicitly know the name of the class you're trying to instantiate. When building templates, I find I'm often in a position where I try to instantiate a class whose name is being supplied dynamically through an XML string or a naming convention of some kind. In these situations I use the second solution I found for dynamically creating instances of symbols.

When the name of the class is not explicitly known, the UILoader class is used, as shown in the code below:

import fl.containers.UILoader;
 
// Attach movie
var myInstance = new UILoader();
myInstance.scaleContent = false;
myInstance.source = "myClassName";
addChild(myInstance);

Note: This code works well for loading display objects such as bitmaps and movie clips. For loading sounds from the Library, you have to explicitly know the class names.

11. Loading a URL

The getURL command no longer exists in ActionScript 3.0. To call a URL, you will create a URLRequest instance and then call the navigateToUrl method. The try statement below illustrates the type of error handling capable with ActionScript 3.0 exception handling; it shows how to call a URL:

import flash.net.*;
 
var url = "";
var request:URLRequest = new URLRequest(url);
try {           
   navigateToURL(request);
}
catch (e:Error) {
   // Handle error...
}

Changes to building object classes in ActionScript 3.0

The following notes deal with the package keyword, data typing and type checking, changes to event handling, and ensuring that the event's target property is populated:

12. The package keyword

The structure of an ActionScript 3.0 class is not very different from an ActionScript 2.0 class. Perhaps the biggest structural difference is the use of the package keyword to start the ActionScript 3.0 file.

If the class (myClass) is saved into a folder named myCode, then the structure of the class file looks like this:

package myCode
{
   import flash.display.MovieClip;
 
   public class myClass extends MovieClip
   {
      function myClass(){
         // write out class as usual from here...
      }
   }
}

13. Data typing and type checking

ActionScript 3.0 contains some new operators that can be used for data typing, type checking, and type casting. I found these operators to be very useful when I was working with events or scanning through display objects looking for specific types.

To cast an instance as a movie clip when the compiler considers it to be something else, use the as keyword, as shown below:

(loader.content as MovieClip).play();

To check to see if an object is a certain type of class, use the is keyword, like this:

if( myInstance is myClass )
{
   // do something...
}

Note: The is operator replaces the instanceof operator in previous versions of ActionScript.

14. Changes to event handling

Events have evolved in ActionScript 3.0. The event handling metaphor common to ActionScript 2.0 components has become part of all display objects in ActionScript 3.0. The big picture is that all objects in Flash now share a common event model. Along with standardization in ActionScript 3.0 comes a few changes to how event handler functions work. In the new model, the addEventListener method expects a function reference for the listener instead or an object or a function reference. In ActionScript 2.0 it was common to use an object as a container for a number of event handler functions, but in ActionScript 3.0 listeners appear as functions per event or as functions containing switch statements to handle multiple events.

The following code illustrates how a mouse event handler is assigned to a button:

import flash.events.MouseEvent;
function clickHandler(event:MouseEvent):void
{
   // Handle event here...
}
addEventListener(MouseEvent.CLICK, clickHandler);

15. Ensuring the event's target property is populated

I found that creating custom controls in ActionScript 3.0 is easy to do. However, I ran into issues when listening to events from the custom controls. When developing an application, I often handle events from multiple components in a single event handler function. I usually use the event object's target property as a way to reference back to the object that broadcast the event. The problems I encountered were due to the fact that the event object's target property arrived at the event handler function as an empty value. Because I didn't have a way to reference back to the original object, I had a hard time setting up a dynamic environment.

After a bit of digging through the Flash user interface component code, I realized that there are extra parameters associated with the addEventListener command. I found out why the target property was empty: the event system was deleting the reference to the target before it was sent to my event handler. The solution to resolve this issue is to change the garbage collection settings by adjusting the optional parameters that appear at the end of the addEventListener command.

I placed the following code inside the custom button controls to make sure the event's target property remains populated:

import flash.events.MouseEvent;
function clickHandler(event:MouseEvent):void
{
   // Do something on click...
}
addEventListener(MouseEvent.CLICK,clickHandler,false,0,true);

Notice that the last parameter is set to true. This is the setting that causes the event system to leave the reference to the event's target.

Where to go from here

These are the most important items that came to my attention as I learned ActionScript 3.0. For more information, visit the ActionScript Technology Center in the Developer Center.

See also the ActionScript 2.0 Migration reference for complete details on the changes from ActionScript 2.0 to ActionScript 3.0.

Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License

About the author

Dan Carr is owner, lead developer, and trainer for Dan Carr Design in San Francisco. With years of history developing for Macromedia and Adobe, Dan has created a range of features available in Flash, including e-learning templates, UI components, and Developer Resource Kit extensions. Dan teaches Flash design and ActionScript classes in San Francisco and develops e-learning and web applications for the public, as well as for Adobe product teams.