The Display List: Chapter 4 - Learning ActionScript 3.0

by Rich Shupe and Zevan Rosser

This excerpt is from Learning ActionScript 3.0. Learning ActionScript 3.0 gives you a solid foundation in the Flash language and demonstrates how you can use it for practical, everyday projects. The book does more than give you a handful of sample scripts, defining how ActionScript and Flash work. It gives you a clear look into essential topics such as logic, event handling, displaying content, migrating legacy projects to ActionScript 3.0, classes, and much more. Written for those new to the language, this book doesn't rely exclusively on prior knowledge of object-oriented programming (OOP). Instead, it helps you expand your skillset by first focusing on clear, concise examples in the timeline, evolving into OOP examples over time-allowing you to choose the programming approach with which you are most comfortable.

buy button

One of the most dramatic changes introduced by ActionScript 3.0, particularly for designers accustomed to prior versions of ActionScript, is the way in which visual elements are added to an application at runtime. In prior versions of ActionScript, a separate approach was used to add most kinds of visual assets at runtime, requiring varied syntax. Management of those assets—particularly depth management—and creating and destroying objects, were also fairly restrictive and could be relatively involved depending on what you were trying to accomplish.

ActionScript 3.0 brings with it an entirely new way of handling visual assets. It's called the display list. It's a hierarchical list of all visual elements in your file. It includes common objects such as movie clips, but also objects such as shapes and sprites that either didn't previously exist or could not be created programmatically.

In this chapter, we'll look at the following topics:

  • The Sum of Its Parts. Understanding the display list means understanding its parts. In addition to knowing the kinds of objects that can be part of the display list, it's also important to grasp the simple difference between display objects and display object containers.
  • Adding and Removing Children. The best part of the display list is how easy and consistent it is to add objects to, and remove objects from, the list.
  • Managing Object Names, Positions, and Data Types. In addition to adding and removing display objects, you will need to manipulate existing members of the display list. You will likely need to find an object, either by name or position in the list, or even identify an object's data type as a particular display object class.
  • Changing the Hierarchy. It's also much easier than ever before to manage asset depths (z-order, or the visual stacking order controlled by ActionScript, rather than timeline layers), and to change the familial relationship of assets. Moving a child from one parent to another is a breeze.
  • A Dynamic Navigation Bar. As a quick demonstration of using the display list, we'll show you how to dynamically generate a very simple navigation bar.

Section 4.1: The Sum of Its Parts

Example
Figure 4-1: The visual layout of the simple file structure

If you start thinking about the display list by thinking about what you see in any given application, you're half-way home. In addition to contributing to the structure of the new event model, discussed in , the display list is responsible for maintaining the visual and spatial assets in your file. You will use the display list to create and destroy visual assets, to manage their coexistence, and manage how they interrelate.

Let's take a look at the contents of the display list of a simple file structure. shows that this file has a shape, a text element, and a movie clip, and inside the movie clip is a bitmap. shows the display list of the same structure.

At the top of the list is the stage. Although you can access the stage from many objects in the display list, it's easiest to think of the stage as the foundation on which everything is built. It also helps to think of the stage as the ultimate container within which all your visual assets reside at runtime. The container analogy will soon become central to this discussion. The stage contains everything.

Example
Figure 4-2: The display list of the sample filee

Next is the main timeline, which is also referenced using the root display object instance variable. (See the sidebar, "_root versus root" for more information.) Like the stage, a Flash file requires one timeline within which all other assets are contained. Because of event propagation, it is common to use the main timeline as a location to add event listeners when writing scripts in the timeline. In that context, the main timeline is typically referenced using the this identifier, as in "this object being currently referenced within the context of the script." (For more information about event listeners and event propagation, see . For more information about this, see Chapter 2.)

Below the main timeline in the display list hierarchy are all the visual assets in the file. Included in the sample display list are the aforementioned shape, text, and movie clip assets, and inside the movie clip is the bitmap.

You may notice in that everything is subtitled as a display object or display object container. This is key to understanding and working with the display list effectively. It probably follows that everything in the display list is a display object. However, some display objects can contain other elements and therefore also display object containers.

For example, a shape is a display objects, as are bitmaps and videos. However, none of these items can have children, so the display list lineage ends there. A movie clip can have children, such as other movie clips therein. Therefore, although a movie clip is a display object, it is also a display object container. This concept of display objects also possibly being containers is useful when traversing the display list, determining whether a display object has children, moving a child from one parent to another, and so on.

_root versus root

You may have heard you should avoid using the global _root variable in prior versions of ActionScript. That's because the value of the variable was subject to change. Before ActionScript 3.0, the _root variable referred to the timeline of the original host SWF no matter how many SWFs got loaded.

_root was the equivalent of an absolute address, like referring to an image in a web site as http://www.yourdomain.com/image, or a file on your computer as C:\directory\file, instead of a more flexible relative address such as "image" (or "../image," for example, if you needed to traverse directories first).

Because _root was an absolute address, if the file in which you used the global variable was loaded into another file, the variable was redefined to become the timeline doing the loading, rather than your original file. This was often not initially intended and would break many object path references that originated with _root.

In ActionScript 3.0, the display list changed that prevailing logic. root is now an instance variable of the display object, and doesn't always refer to the main timeline. It's relevant to the context in which it's used so it behaves more like a relative address and no longer changes just because your SWF is loaded into another SWF. The root of a movie clip in SWF A, is the same if it stands alone or is loaded into SWF B. The same goes for the root in SWF B, whether it stands alone or is loaded into SWF C, and so on.

Display List Classes

In just a moment, we'll walk through a typical ActionScript display list that demonstrates the distinction between display objects and display object containers. First, however, take a look at the individual classes that contribute to the display list, as shown in Figure 4-3.

Example
Figure 4-3: The Display List classes

We discussed classes in Chapter 1, and we'll be using them extensively as we delve deeper into the book. For now, however, and in this context, just think of these classes as objects that can be part of the display list. As you look through Figure 4-3, for instance, you'll recognize Shape, Bitmap, Video, and so on.

It is important to note, however, that, unlike 4-2, this is not a hierarchical depiction of an actual display list. For example, it is possible for shapes, bitmaps, videos, and static text, among other items, to exist inside movie clips. Yet in the diagram in 4-3, MovieClip appears to be lowest in the display list hierarchy, making this seem impossible in the traditional flowchart sense.

The key to this apparent dichotomy is that the display list classes originate with the DisplayObject class, and the flowchart shows the descendents of that class. Figure 4-3 is hierarchical, but it shows the possible objects that can be a part of any display object. Because a display object is anything that is, or can be, part of the display list, this flowchart is valid not only when examining the contents of the stage, but also when examining the contents of a movie clip, for example.

Here is a quick description of the classes in 4-3, rearranged slightly for clarity of discussion.

DisplayObject
Anything that can exist in the display list is a display object, and more specialized classes are derived from DisplayObject.
Shape
This is a rectangle, ellipse, line, and so on, created with drawing tools. New to ActionScript 3.0, you can now create these at runtime.
Bitmap
This is an ActionScript bitmap created at runtime using the BitmapData class. Note that a standard JPG import does not create this kind of bitmap, but rather creates a shape. After creating a bitmap with this class, however, you can place an imported JPG into it for display.
Video
This is a video display object, the minimum required to play a video, rather than a video component.
InteractiveObject
This class includes any display object the user can interact with using the mouse or keyboard. It is not used directly to manipulate the display list. Instead, you work with its descendents.

Skipping a bit, temporarily, and moving down a level:

SimpleButton
This class is used to create a button that's functionally equivalent to the buttons you probably have experience with in the authoring interface. However, in ActionScript 3.0, you can now create buttons on the fly by using other display objects for their up, over, down, and hit states.
TextField
This class includes dynamic and input text elements, controllable with ActionScript.
DisplayObjectContainer
This class is similar to DisplayObject in that it refers to multiple display object types. The difference here, however, is that this object can contain children. All display object containers are display objects, but only display objects that can have children are display object containers. For example, a video is a display object, but it cannot have children. A movie clip is a display object, and it can have children, so it's also a display object container. Usually, you will work directly with this class when traversing the display list, looking for children or ancestors. Usually, you will manipulate one or more of its descendent classes.

There are four kinds of display object containers:

Stage
Remember, the stage itself is part of the display list. This class demonstrates that any interactive object can reference the stage which, itself, is a display object container.
Sprite
New to ActionScript 3.0, a sprite is simply a movie clip without a timeline. Many ActionScript manipulations typically performed using movie clips only require one frame of the created movie clip's timeline. So, the size and administrative overhead of the timeline is unnecessary. As you become more accustomed to ActionScript 3.0, and begin to consider optimization more frequently, you may find yourself using sprites more than movie clips.
Loader
This class is used to load external assets destined for the display list, including bitmaps and other SWFs.
MovieClip
This is the movie clip you probably know and love, as a result of creating them in the authoring interface, via ActionScript, or both.

We left three items from the second tier for last, as you will probably use these classes the least often:

AVM1Movie
This class is for working with loaded SWFs created using ActionScript 1.0 or 2.0. AVM1, (which stands for ActionScript Virtual Machine 1) is reserved for SWFs that use ActionScript 1.0 and/or ActionScript 2.0, while AVM2 is used for SWFs that use ActionScript 3.0. Because Flash Player uses two discrete code bases, these virtual machines are not compatible. The AVM1Movie class provides a way of manipulating display properties of legacy SWFs, but does not facilitate communication between ActionScript 3.0 and older SWFs. This must be accomplished by other means, such as LocalConnections. We will discuss these other methods in .
MorphShape and StaticText
These two classes represent a shape tween and static text element, respectively, neither of which are controllable directly via ActionScript. However, they are part of the display classes because they inherit properties, methods, and events from their DisplayObject parent class. This makes it possible to rotate a static text element, for example.

Once you begin using the display list frequently—especially if you are familiar with the ActionScript 2.0 method of doing things—you will quickly become enamored with its power, flexibility, and simplicity. We will show you how to perform several common display list tasks in this chapter but, if you take one thing away from this initial discussion, it should be a basic understanding of display object versus display object container. To demonstrate this effectively, let's look at a short segment of code that traces requested content of the display list to the output window.

Displaying the Display List

It's sometimes useful, especially when you're creating many display objects with potentially complicated nested objects, to walk through the display list and analyze its contents. This little function, found in the companion source file trace_display_list.fla will trace the contents of any display object.

1 function showChildren(dispObj:*):void {
2    for (var i:int = 0; i< dispObj.numChildren; i++) {
3         var obj:DisplayObject   = dispObj.getChildAt(i);
4         if (obj is DisplayObjectContainer) {
5             trace(obj.name, obj);
6             showChildren(obj);
7         } else {
8             trace(obj);
9         }
10     }
11 }
12
13 showChildren(stage);

Lines 1 and 11 define the function showChildren(), which requires as its argument the display object you wish to analyze. (See the adjacent note for more information on the use of the asterisk datatype.) Line 13 calls the function and, in this case, passes in the stage for analysis. In this example, the function will trace the contents of all children of the stage.

Lines 2 and 10 define a for loop, which will loop until there are no more children in the display object passed into the function. The number of loops is determined by the numChildren property, which returns an integer representing the number of nested display objects in the object being analyzed. Each time through the loop, line 3 populates the obj variable with the next child in the display list using the getChildAt() method. This determines the child display object at the level indicated by the loop counter (i). The first time through the loop, when i is 0, the first child will be returned. The second time when i is 1, the second child will be returned, and so on.

Line 4 is what makes this function handy. It first checks to see whether the display object currently being analyzed is also a display object container. It does so by using the new is operator, which checks the data type of the object in question, comparing it against the DisplayObjectContainer type. This is important because if the display object is not a container, the walk through is over for that portion of the display list. The if statement will evaluate to false, jumping down to lines 7 and 8, and the object will be traced. The conditional then ends at line 9, and the code increments and goes through the loop again.

If the display object is also a container, it may have children, so the walk must continue down through that branch of the list. The if statement will evaluate to true, and the object (along with its name, in this case) is traced at line 5.

Finally, at line 6, the function calls itself again. passing in the object currently being inspected. This concept is called recursion. A function calling itself may seem redundant, but it can be very useful. In this case, each time the function is called, it receives a new display object to analyze, so the function reports the contents of that specific display object. The result is a complete walkthrough of all display objects, no matter how many children each may have.

Pages: 1, 2, 3, 4

Next Pagearrow