Book HomeActionScript: The Definitive GuideSearch this book

10.10. Movie-Playback Movie Clip Events

The following events are generated without user intervention as Flash loads and plays movies.

10.10.1. enterFrame

If you've ever resorted to empty, looping movie clips to trigger scripts, enterFrame offers a welcome respite. The enterFrame event occurs once for every frame that passes in a movie. For example, if we place the following code on a movie clip, that clip will grow incrementally by 10 pixels per frame:

onClipEvent (enterFrame) {
  _height += 10;
  _width += 10;
}

(Notice that, as we learned earlier, the _height and _width properties are resolved within the scope of the clip to which the enterFrame event handler is attached, so no clip instance name is required before _height and _width.)

TIP

The enterFrame event is generated before each frame is rendered even if the playhead of the clip with the enterFrame handler is stopped. The enterFrame event, hence, is always being triggered.

When displayed in the Flash Player, all Flash movies are constantly running, even when nothing is moving on screen or when a movie's playhead is stopped on a frame. An individual movie clip's enterFrame handler will, hence, be executed repeatedly for as long as that clip is on stage, regardless of whether the clip is playing or stopped. If a clip's playhead is moved by a gotoAndStop( ) function call, the clip's enterFrame event handler is still triggered with each passing frame. And if every playhead of an entire movie has been halted with a stop( ) function, all enterFrame event handlers on all clips will still execute.

The enterFrame event is normally used to update the state of a movie clip repeatedly over time. But an enterFrame event handler need not apply directly to the clip that bears it -- enterFrame can be used with a single-frame, empty clip to execute code repeatedly. This technique, called a clip event loop (or more loosely, a process) is demonstrated in Section 8.7, "Timeline and Clip Event Loops" in Chapter 8, "Loop Statements".

Note that the code in an enterFrame event handler is executed before any code that appears on the timeline of the clip containing the handler.

With a little ambition, we can use enterFrame to gain extremely powerful control over a clip. Example 10-7, shown later, extends our earlier clip-enlarging code to make a movie clip oscillate in size.

10.10.2. load

The load event occurs when a movie clip is born -- that is, when a movie clip appears on stage for the first time. A movie clip "appears on stage" in one of the following ways:

The body of a load event handler is executed after any code on the timeline where the movie clip first appears.

A load event handler is often used to initialize variables in a clip or to perform some setup task (like sizing or positioning a dynamically generated clip). A load handler can also provide a nice way to prevent a movie clip from automatically playing:

onClipEvent (load) {
  stop( );
}

The load event handler might also be used to trigger some function that relies on the existence of a particular clip in order to execute properly.

The load event is particularly interesting when combined with the duplicateMovieClip( ) function, which creates new movie clips. In Example 10-2 we generate an entire field of star clips using a single load event handler in a cascading chain. The load handler is copied to each duplicated star, causing it, in turn, to duplicate itself. The process stops when the 100th clip is duplicated. The .fla file for Example 10-2 is available from the online Code Depot.

Example 10-2. Generating a Star Field with a load Event

onClipEvent (load) {
  // Place the current clip at a random position
  _x = Math.floor(Math.random( ) * 550);    
  _ y = Math.floor(Math.random( ) * 400);
  
  // Reset clip scale so we don't inherit previous clip's scale
  _xscale = 100;
  _ yscale = 100;

  // Randomly size current clip between 50 and 150 percent
  randScale = Math.floor(Math.random( ) * 100) - 50;
  _xscale += randScale;
  _ yscale += randScale;  

  // If we're not at the 100th star, make another one
  if (_name != "star100") {
    nextStarNumber = number(_name.substring(4, _name.length)) + 1;
    this.duplicateMovieClip("star" + nextStarNumber, nextStarNumber);
  }
}

10.10.3. unload

The unload event is the opposite of the load event: it occurs when a movie clip expires -- that is, immediately after the last frame in which the clip is present on stage (but before the first frame in which the clip is absent).

The following incidents provoke a movie clip's unload event:

This last unload event trigger may seem a little odd but is actually a natural result of the way movies are loaded into Flash. Anytime a .swf is loaded into a movie clip, the previous contents of that clip are displaced, causing an unload event. Here's an example that illustrates the behavior of the load and unload events in connection with loadMovie( ) :

  1. In the Flash authoring tool, we place an empty movie clip on stage at frame 1 of a movie's main timeline. We name our clip emptyClip.

  2. At frame 5 of the main timeline, we load the movie test.swf into emptyClip using the following code: emptyClip.loadMovie("test.swf");

  3. We play the movie using Control Play movie.

The results are:

  1. Frame 1: The emptyClip clip appears, causing a load event.

  2. Frame 5: The loadMovie( ) function is executed in two stages:

    1. The placeholder content of emptyClip is removed to make room for the incoming test.swf, causing an unload event.

    2. The movie test.swf loads, causing a load event.

The unload event is typically used to initiate housecleaning code -- code that cleans up the Stage or resets the program environment in some way. An unload handler also provides a means for performing some action (such as playing another movie) after a movie clip ends.

10.10.4. data

The data event occurs when external data is loaded into a movie clip. The data event can be triggered by two quite different circumstances, according to the kind of data being loaded. We'll consider those circumstances separately.

10.10.4.1. Using a data event handler with loadVariables( )

When we request a series of variables from a server using loadVariables( ), we must wait for them to load completely before using their information. (See Part III, "Language Reference".)

When a movie clip receives the end of a batch of loaded variables, the data event is triggered, telling us it's safe to execute code that relies on the variables.

For example, suppose we have a guest book movie in which visitors enter comments and we store those comments on a server. When a user attempts to view a comment, we request it from the server using loadVariables( ). But before we can display the comment, we must pause at a loading screen until we know that the requested data is available. A data event handler tells us when our data has loaded, at which point we can safely display the comment to the user.

Example 10-3 is a simplified excerpt of some code from a guest book showing a data event handler used with loadVariables( ). In the example, a button loads two URL-encoded variables from a text file into a movie clip. The movie clip bears a data event handler that executes when the variables have loaded. From inside that handler, we display the values of the variables. We know the variables are safe to display because the code in the handler isn't executed until triggered by the data event (i.e., after the data is received).

Example 10-3. Waiting for a data Event

// CONTENT OF OUR guestbook.txt FILE
name=judith&message=hello

// BUTTON INSIDE OUR CLIP
on (release) {
  this.loadVariables("guestbook.txt");
}

// HANDLER ON OUR CLIP
onClipEvent (data) {
  trace(name);
  trace(message);
}

We'll use the data event again when we build a Flash form in Chapter 17, "Flash Forms".

10.10.4.2. Using a data event handler with loadMovie( )

The second use of the data event relates to the loading of external .swf files into movie clips with the loadMovie( ) function. When a .swf file is loaded into a host clip, by default the file begins playing immediately, even if only partially loaded. This is not always desirable -- sometimes we want to guarantee that all or a certain percentage of a .swf has loaded before playback begins. We can make that guarantee with a data event handler and some preloading code.

The data event occurs each time a host movie clip receives a portion of an external .swf file. The definition of what constitutes a "portion" is more complex than you might expect. In order for a data event to be triggered, at least one complete new frame of the external .swf file must have loaded since either: (a) the last data event fired or (b) the .swf file started loading. (More than one frame of the .swf file may actually have loaded in that amount of time, but one frame is the minimum number required to prompt a data event.)

The execution of data event handlers is tied to the rendering of frames in the Player. With every frame rendered, the interpreter checks to see if part of an external .swf file has been loaded into a clip that has a data event handler. If part of an external .swf file has been loaded into such a clip, and the loaded portion contains at least one new frame, then the data event handler is executed. This process happens once -- and only once -- per frame rendered (even if the playhead is stopped).

Note that because the data event happens on a per-frame basis, movies with higher frame rates tend to have smoother-looking preloaders because they receive more frequent updates on the status of loading .swf files.

The exact number of data events triggered during a loadMovie( ) operation depends on the distribution of content in the .swf file being loaded and the speed of the connection. A single-frame .swf file, no matter how large, will trigger only one data event. On the other hand, a .swf file with 100 frames may trigger up to 100 separate data events, depending on the movie's frame rate, the byte size of each frame and the speed of the network connection. If the frames are large and the connection is slow, more data events will be triggered (up to a maximum of one per frame). If the frames are small and the connection is fast, fewer data events will be triggered (the entire 100 frames may be transferred between the rendering of two frames in the Player, prompting only one data event).

So how do we use a data event handler to build a preloader? Well, whenever a data event occurs due to a loadMovie( ) function call, we know that an external .swf file download is in progress. Therefore, from inside a data event handler, we can check whether enough of the file has downloaded before allowing it to play. We do so using the getBytesLoaded( ) and getBytesTotal( ) functions as shown in Example 10-4. (The _framesloaded and _totalframes movie clip properties may also be used.)

Example 10-4 also provides feedback while the movie is loading. Note that the .swf file being loaded should have a stop( ) function call on its first frame to prevent it from automatically playing before it is completely downloaded. A variation of Example 10-4 is available from the online Code Depot.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.