DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 12.12 Creating a Component That Subclasses MovieClip

12.12.1 Problem

You want to create a reusable component, such as an interface widget, or even a component without a UI.

12.12.2 Solution

Create a new movie clip symbol. On the first frame of the symbol's timeline define the component class (which must inherit from MovieClip). Then register the class using Object.registerClass( ). All this code should be encapsulated between #initclip and #endinitclip pragmas.

12.12.3 Discussion

Components are a way of encapsulating movie clips so that the instances can be easily configured by setting parameters through a user interface at authoring time or through a programmatic interface at runtime. For those who prefer to use Flash as a design tool, many ready-made components (such as those included in the Flash UI Component sets) can be dragged into a movie, and parameters can be set via the Property inspector or Parameters panel. These components add functionality to the movie without the designer having to write all the code that is entailed. For our purposes, however, we will use the term "component" more specifically to refer to subclasses of MovieClip. In other words, we will be discussing components that are controlled programmatically instead of those that are controlled via an author-time user interface.

There are five (or six) basic steps to creating a component:

  1. Create a new movie clip symbol and give it a name in the Symbol Property dialog box (accessed under Properties from the Library panel's pop-up Options menu). As a best practice, use the name you want to give to your component (such as MyComponent).

  2. Export the movie clip symbol for ActionScript usage (using Linkage from the Library panel's pop-up Options menu). As a best practice, give the symbol a linkage identifier that follows the naming convention of ComponentNameSymbol (such as MyComponentSymbol).

  3. Define the component class on the first frame of the component timeline. The class should follow these guidelines:

    1. As a best practice, name the class ComponentNameClass (such as MyComponentClass).

    2. The class constructor should not take any parameters.

    3. The class must inherit from MovieClip by assigning to the prototype property a new MovieClip instance. (Subclassing the MovieClip class is the only time you use a MovieClip constructor in a new statement.)

  4. After defining the class, register it using Object.registerClass( ). The first parameter should be the symbol linkage identifier name specified as a string. The second parameter should be a reference to the class.

  5. Place all the code for the component (the class definition and the registration code) between #initclip and #endinitclip pragmas so that the component class is defined and registered before it is called. This is essential. Without the #initclip pragma, the component class is loaded only after instances of the component are loaded into the movie.

  6. The sixth step in creating a component is to specify the component definition for the symbol and optionally create a custom UI. You can read more about this process in the Macromedia technote, "Creating components in Macromedia Flash MX" at http://www.macromedia.com/support/flash/applications/creating_comps. For our purposes, we will consider this step optional. Technically, a component is a component only if you have completed this step. But this step only enables an author-time interface for configuring the component instances—something we are not particularly interested in from an ActionScript standpoint.

Using our working definition, components are the only way to effectively subclass MovieClip, so they are the only way to create custom object classes with a visual aspect. Basic components can be created that do not subclass MovieClip. These types of components allow users to set values in the Component Parameters panel at authoring time but not via ActionScript. Basic components cannot be instantiated with ActionScript. In contrast, you can use ActionScript to control MovieClip subclass components and can even instantiate them using the attachMovie( ) method. Because a component class is registered to a particular linkage identifier name, Flash automatically knows to call the component class constructor function when a new instance of the symbol is created using attachMovie( ).

Here is an example in which a component, MyComponent, is created and used within a movie. The component creates a text field within itself and has methods that allow it to move about the screen to random spots at a set interval.

  1. Create a new movie clip symbol named MyComponent.

  2. Open the Linkage properties for MyComponent using the Library panel's pop-up Options menu. Export the symbol for ActionScript and give it a linkage identifier of MyComponentSymbol.

  3. On the first frame of the default layer of MyComponent, add the following code:

    // Make sure everything is between the #initclip and #endinitclip pragmas.
    #initclip
    
    // The constructor function accepts no parameters.
    function MyComponentClass (  ) {
    
      // Create a text field that auto sizes. Set an initial text value.
      this.createTextField("myTextField", 1, 0, 0, 0, 0);
      this.myTextField.autoSize = true;
      this.myTextField.text = "init text value";
    }
    
    // MyComponentClass subclasses MovieClip, as must all scriptable components.
    MyComponentClass.prototype = new MovieClip(  );
    
    // Define a method that sets the text.
    MyComponentClass.prototype.setText = function (val) {
      this.myTextField.text = val;
    };
    
    // The beginMove(  ) method uses setInterval(  ) to call the move(  ) method of the
    // component at the specified rate. The interval reference is stored in a
    // property so that it can be removed later.
    MyComponentClass.prototype.beginMove = function (rate) {
      this.moveInterval = setInterval(this, "move", rate);
    };
    
    // The endMove(  ) method calls clearInterval(  ) to stop the calls to move(  ).
    MyComponentClass.prototype.endMove = function (  ) {
      clearInterval(this.moveInterval);
    };
    
    // The move(  ) method is called automatically at an interval when beginMove(  ) is
    // called. This method sets the _x and _y properties of the component to random
    // values within the Stage.
    MyComponentClass.prototype.move = function (  ) {
      this._x = Math.random(  ) * 550;
      this._y = Math.random(  ) * 400;
    };
    
    // Register the component class to the linkage identifier for the symbol.
    Object.registerClass("MyComponentSymbol", MyComponentClass);
    
    #endinitclip
  4. Return to the first frame of the main timeline and add the following code to create an instance of the component:

    // Create a new instance of the component. Because MyComponentClass is registered 
    // to the MyComponentSymbol linkage identifier, when this new instance is
    // created, it will automatically call the MyComponentClass constructor. 
    _root.attachMovie("MyComponentSymbol", "myC", 1);
    
    // Call the beginMove(  ) method with a rate of 100. This causes the component to
    // move approximately 10 times per second.
    myC.beginMove(100);
    
    // Define an interval callback function that calls the endMove(  ) method for myC 
    // and clears the interval.
    function doEndMove (  ) {
      myC.endMove(  );
      clearInterval(cInterval);
    }
    
    // Set an interval at which doEndMove(  ) is called after 10 seconds have elapsed.
    cInterval = setInterval(doEndMove, 10000);

12.12.4 See Also

Chapters 14 and 16 of ActionScript for Flash MX: The Definitive Guide cover movie clip subclasses and component development in detail.

    [ Team LiB ] Previous Section Next Section