Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Beginning ActionScript 2.0 2006

.pdf
Скачиваний:
101
Добавлен:
17.08.2013
Размер:
12.47 Mб
Скачать

Chapter 7

Creating Movie Clips On-the-Fly

Now you’re ready to apply some of the MovieClip class methods. The first task for working with movie clips is to place them on the stage. You can create a new movie clip in two ways:

Create a new movie clip symbol in the library, drag it to the desired location on the stage, and give it an instance name in the properties panel. The limitation of this approach is that if the implementation of this particular clip is to change later on, it will likely need to be changed both within the project file and within the ActionScript code.

Use the createEmptyMovieClip() method. This technique enables complete programmatic control over how a project is structured.

createEmptyMovieClip() is fundamental to building interfaces using ActionScript. With this method, it is possible to create an entire project with code that is script-generated and that sits on just one frame in the main timeline.

Each movie clip must have a parent movie clip. If no movie clips are on the stage yet, use the base timeline as the parent movie clip. The following line creates a movie clip on the main timeline:

_level0.createEmptyMovieClip(“firstClip”, 1);

The _level0 reference is an absolute reference. The problem with using it is that if you were to later load your project into a movie clip in a different project, the _level0 reference would have to be changed to refer to the location of the new movie clip. In the context of movie clips, the this keyword is a relative reference that refers to the timeline holding the code. In this case, it would refer to the timeline at _level0. If it is later loaded into a movie clip in a different project, the reference resolves to the new parent movie clip and doesn’t have to be changed. Here’s how to create a movie clip on the current timeline using a relative reference:

this.createEmptyMovieClip(“firstClip”, 1);

The instance name parameter provides a way to access the new movie clip once it has been created. You can refer to the new movie clip in three ways:

Through the reference that the method returns on completion. This is a handy way to hold onto a movie clip reference when creating multiple clips with a loop, especially when that clip needs to be referenced many times in a single iteration. Here’s an example that assigns the new movie clip to a variable handle, and then uses that handle to manipulate the position of the movie clip:

var movieClipHandle:MovieClip = this.createEmptyMovieClip(“firstClip”, 1);

movieClipHandle._x = 20;

By referencing the variable created on the timeline. This is good to use when creating one movie clip at a time. The following code demonstrates that once you create a movie clip, it automatically creates a variable on the timeline that you can use to access the new movie clip:

this.createEmptyMovieClip(“firstClip”, 1); this.firstClip._x = 20; // or firstClip._x = 20; // ‘this’ is implied

178

Controlling Movie Clips

Through the associative array syntax. Recall from Chapter 2 that object properties can be accessed either through dot notation or through associative array notation. A movie clip is itself a property of its parent movie clip, and it is thus also available through the associative array syntax. Like the first technique, this is handy when creating multiple movie clips within a loop. The following example shows how the associative array syntax is used:

this.createEmptyMovieClip(“firstClip”, 1);

this[“firstClip”]._x = 20;

When assigning a depth parameter for the new movie clip, the depth number must be unique within the parent movie clip. No two movie clips with the same parent can share the same depth. If a new movie clip is assigned a depth that is already in use, the item that already occupies that depth is removed from the stage. In the following example, a movie clip is created on depth number 1, and then a second movie clip is created on the same depth. Once the second movie clip has been created, the first one is destroyed.

this.createEmptyMovieClip(“firstClip”, 1); trace(firstClip);

// Outputs: _level0.firstClip

this.createEmptyMovieClip(“secondClip”, 1); trace(firstClip);

//Outputs: undefined trace(secondClip);

//Outputs: _level0.secondClip

The best practice for assigning depths to movie clips is to use the getNextHighestDepth() method. It works in version 7 of the player and later, and it prevents depths from conflicting. The following code shows that when you use this method, you don’t have to worry about accidentally destroying another movie clip by allocating a depth number that’s already been assigned:

this.createEmptyMovieClip(“firstClip”, this.getNextHighestDepth()); trace(firstClip);

// Outputs: _level0.firstClip

this.createEmptyMovieClip(“secondClip”, this.getNextHighestDepth()); trace(firstClip);

//Outputs: _level0.firstClip trace(secondClip);

//Outputs: _level0.secondClip

Try It Out

Create a Simple Button

Creating a new movie clip only requires a single line of code; working with it can be as complex as you want it to be. This exercise demonstrates a function that creates a new movie clip, draws inside of it, gives it a label, and makes it clickable.

1.Create a new Macromedia Flash document by selecting File New and choosing Flash Document from the New Document panel.

2.Click the first frame in the timeline, open the Actions panel (Window Development Panels Actions), and type in the following ActionScript code:

#include “tryItOut_createButton.as”

179

Chapter 7

3.Select File Save As, name the file tryItOut_createButton.fla, choose an appropriate directory, and save it.

4.Create a new Macromedia Flash document by selecting File New and choosing ActionScript File from the New Document panel.

5.Select File Save As, ensure it is showing the same directory containing the Flash project file, name the file tryItOut_createButton.as, and save it.

6.Type the following code into the new ActionScript file:

function createButton(buttonName:String, buttonLabel:String, ; parentClip:MovieClip, xPos:Number, yPos:Number) : Void

{

var newClip:MovieClip = this.createEmptyMovieClip(buttonName, ; parentClip.getNextHighestDepth());

newClip._x = xPos; newClip._y = yPos;

newClip.moveTo(0, 0); newClip.lineStyle(1, 0x000000); newClip.beginFill(0xCCCCCC, 100); newClip.lineTo(100, 0); newClip.lineTo(100, 20); newClip.lineTo(0, 20); newClip.lineTo(0, 0); newClip.endFill();

newClip.createTextField(“labelField”, newClip.getNextHighestDepth(), ; 5, 3, 100, 20);

newClip.labelField.text = buttonLabel;

newClip.onRelease = function()

{

trace(“Pressed button: “ + this._name);

}

}

createButton(“button1”, “Button One”, this, 20, 20);

7.Save the file, return to the Macromedia Flash project file, and select Control Test Movie.

How It Works

The first line of code in the function creates a movie clip and assigns a reference to it to a local variable:

var newClip:MovieClip = this.createEmptyMovieClip(buttonName, ; parentClip.getNextHighestDepth());

Next, the clip is positioned:

newClip._x = xPos; newClip._y = yPos;

180

Controlling Movie Clips

A background and an outline are drawn:

newClip.moveTo(0, 0); newClip.lineStyle(1, 0x000000); newClip.beginFill(0xCCCCCC, 100); newClip.lineTo(100, 0); newClip.lineTo(100, 20); newClip.lineTo(0, 20); newClip.lineTo(0, 0); newClip.endFill();

Note that this code could have used the associative array syntax instead. For example, the following code is also valid:

this.createEmptyMovieClip(buttonName, parentClip.getNextHighestDepth());

parentClip[buttonName]._x = xPos; parentClip[buttonName]._y = yPos;

parentClip[buttonName].moveTo(0, 0); parentClip[buttonName].lineStyle(1, 0x000000); parentClip[buttonName].beginFill(0xCCCCCC, 100); // etc...

As you can see, when there are frequent references to the same movie clip, it is neater to assign to a short temporary variable and to use that variable throughout.

Next, a new text field is created, and a label is assigned:

newClip.createTextField(“labelField”, newClip.getNextHighestDepth(), ; 5, 3, 100, 20);

newClip.labelField.text = buttonLabel;

The movie clip is then made to behave like a button by defining an onRelease event handler:

newClip.onRelease = function()

{

trace(“Pressed button: “ + this._name);

}

Finally, outside of the function, the createButton() function is called:

createButton(“button1”, “Button One”, this, 20, 20);

Attaching Movie Clips from the Librar y

Creating a new movie clip and then defining the clip content using code can be a fair bit of work, especially if the content involves curves, complex shapes, or many layers. In some cases, it may be simpler to create the content with the authoring tool, and then pull that content from the library and attach it to the stage programmatically. The mechanism that makes this possible is the attachMovie() method.

181

Chapter 7

Two major differences exist between the parameters accepted by attachMovie() and those accepted by createEmptyMovieClip():

attachMovie() requires an ID that corresponds to the linkage ID of the library symbol. You can set a linkage ID for any movie clip in the library by going to the symbol’s library properties window, ensuring the advanced properties are showing, selecting the Export for ActionScript checkbox, and assigning an identifier.

Any library symbol that is set to export for ActionScript will be included in the published .swf file, even if it is not referenced in any code or anywhere on the stage.

attachMovie() accepts an Object parameter that allows for a number of parameters to be sent to the new movie clip instance. This is a handy way to set button properties. The following code snippet shows that the _x and _y properties are given initial values that result in the new movie clip being positioned to an x coordinate of 10 and a y coordinate of 20:

this.attachMovie(“buttonTemplate”, “button1”, 1, {_x:10, _y:20}); trace(button1._x);

//Outputs: 10 trace(button1._y);

//Outputs: 20

Now try this method out for yourself.

Try It Out

Create a Simple Button, Version 2

In this example you perform the same task as in the previous Try It Out, but you use the attachMovie() method and draw out parts of the button with the authoring tool instead of with script.

1.Create a new Macromedia Flash document.

2.Click the first frame in the timeline, open the Actions panel, and type in the following ActionScript code:

#include “tryItOut_attachMovie.as”

3.Open the library (Window Library) and from the menu on the top-right of the library palette, choose New Symbol. The Symbol Properties dialog box opens (see Figure 7-1).

4.Name the symbol buttonTemplate, and make sure that the Movie Clip radio button is selected. Select the Export for ActionScript checkbox, and make sure that the identifier field also contains the text buttonTemplate. Click the OK button. (If you do not see these options, click the Advanced button to reveal them.)

5.Rename the only layer in the timeline Background. Create a new layer in the timeline called

Label.

6.Select the keyframe on the Background layer. Choose the rectangle tool from the Tools palette (Window Tools) and draw on the stage a rectangle that is approximately 100 pixels wide by 25 pixels high.

7.Select the only keyframe on the Label layer. Choose the text tool from the Tools palette and drag from the top left to the bottom right of the rectangle to create a text field that is slightly smaller than the rectangle. Use the resize handle on the text field while still in text field edit mode to adjust the size.

182

Controlling Movie Clips

Figure 7-1

8.With the text field still selected, go to the properties panel (Window Properties) and make sure that the drop-down on the top left of the panel shows Dynamic Text and the text field just below it reads labelField.

9.Select File Save As, name the file tryItOut_attachMovie.fla, choose an appropriate directory, and save it.

10.Create a new Macromedia Flash document. Name it tryItOut_attachMovie.as, and save it in the directory containing the Flash project file.

11.Enter the following code into the new ActionScript file:

function createButton(buttonName:String, buttonLabel:String, ; parentClip:MovieClip, xPos:Number, yPos:Number) : Void

{

var newClip:MovieClip = this.attachMovie(“buttonTemplate”, buttonName, ; parentClip.getNextHighestDepth(), {_x:xPos, _y:yPos});

newClip.labelField.text = buttonLabel;

newClip.onRelease = function()

{

trace(“Pressed button: “ + this._name);

183

Chapter 7

}

}

createButton(“button1”, “Button One”, this, 20, 20);

12.Save the file, return to the Macromedia Flash project file, and select Control Test Movie. Clicking the button should produce a trace statement in the output panel.

How It Works

The first line of code makes a copy of the library symbol with the instance ID buttonTemplate and places it on the stage. It also sets the _x and _y positions for the new movie clip by sending the properties to the method via the initialize properties object:

var newClip:MovieClip = this.attachMovie(“buttonTemplate”, buttonName, ; parentClip.getNextHighestDepth(), {_x:xPos, _y:yPos});

Next, the label is set. Although the text field was created manually in the authoring tool, you interact with it as if it were created with code:

newClip.labelField.text = buttonLabel;

The movie clip is made to behave like a button by defining an onRelease event handler:

newClip.onRelease = function()

{

trace(“Pressed button: “ + this._name);

}

This automatically causes the cursor to change to a hand when the mouse hovers over the movie clip. Finally, the createButton() function is called:

createButton(“button1”, “Button One”, this, 20, 20);

Loading External Movies

Until this point, you’ve been working with content that exists within the same project file. What if you want to load other movies or images? Fortunately, this is pretty straightforward, and once again the movie clip is the container that makes it possible. The media types that can be loaded at runtime include .swf and

.jpg files. With version 8 of the Flash player, .gif and .png files also can be loaded at runtime.

Two primary ways to load an external media file exist: by loading it into its own level, and by loading it into a movie clip container.

Loading Movies into Levels

As you know from Chapter 1, levels are basically stacked movie clips with a special identifier for accessing each clip. Every project has at least one level, and the base level is accessed with the global handle

_level0.

184

Controlling Movie Clips

Technically, you can load images into a level. Practically, levels should be restricted for loading only .swf files. The means to load a .swf file into a level is done through the global function loadMovieNum(). Here’s the general form for that function:

loadMovieNum(url:String, level:Number, [method:String]) : Void

To place a movie into level 10, for example, simply call

loadMovieNum(“http://www.nathanderksen.com/book/sampleAnimation.swf”, 10);

Once loaded, the reference _level10 allows access to this content.

There is, unfortunately, a complication. When loading content into a level, the handle to the level is not created right away. The player first checks to see if the file exists, and if it does exist, the player finds out the size of the media. Only after that process is complete is the handle to the level available, and because it involves a potential trip across a network to a server, there is no way to know for sure when that will be. In the following code snippet, the trace() function shows that the _level10 reference is not yet defined although the request to load a file to level 10 has been made:

loadMovieNum(“http://www.nathanderksen.com/book/sampleAnimation.swf”, 10); trace(_level10);

// Outputs: undefined

A delay is needed until the handle is available for accessing the level. The setInterval() function allows for a repeated test to find out when the level is ready to access. In the following example, setInterval() calls the repositionMedia() function every 200 ms to check whether the _level10 reference is defined. Once it is, the whole level is moved 100 pixels to the right and the setInterval() call is halted:

loadMovieNum(“http://www.nathanderksen.com/book/sampleAnimation.swf”, 10); var intervalID:Number = setInterval(repositionMedia, 200);

function repositionMedia()

{

trace(_level10);

if (_level10 != undefined)

{

_level10._x = 100; clearInterval(intervalID);

}

}

//Outputs:

//undefined //_level1

Several ways exist to determine when movie clip content is ready to use; Chapter 8 gets into the details.

Loading Media into Existing Movie Clips

Although loading content into a level is simple, there are some limitations. For instance, levels cannot be swapped, level numbers have to be manually tracked, and levels cannot be nested within other content.

185

Chapter 7

Using movie clips as containers for loaded content offers greater flexibility than using levels: there is no delay between when a movie clip is created and when the handle is available, there is a mechanism to manage movie clip depths, and movie clips can easily be created and deleted anywhere. Movie clips are also more appropriate for images and can generate a large variety of events based on user interactions.

Loading content into a movie clip is as simple as this:

this.createEmptyMovieClip(“swfHolder”, this.getNextHighestDepth()); swfHolder.loadMovie(“http://www.nathanderksen.com/book/sampleAnimation.swf”);

this.createEmptyMovieClip(“jpgHolder”, this.getNextHighestDepth()); jpgHolder.loadMovie(“http://www.nathanderksen.com/book/afternoonShower.jpg”);

If you target Macromedia Flash Player version 8, you can also load .gif and .png files. If you use the transparency feature of these image formats, the Flash 8 player properly makes those areas transparent. The following code shows what happens when a .png image with a transparent area is viewed over other content, such as another copy of the same image:

this.createEmptyMovieClip(“pngHolder”, this.getNextHighestDepth()); pngHolder.loadMovie(“http://www.nathanderksen.com/book/flowerInDetail.png”);

this.createEmptyMovieClip(“pngHolder2”, this.getNextHighestDepth()); pngHolder2.loadMovie(“http://www.nathanderksen.com/book/flowerInDetail.png”); pngHolder2._x = 60;

pngHolder2._y = 60;

Unlike with levels, the content does not need to start loading before the container movie clip is manipulated. The following code shows scaling take effect immediately, even before the image is displayed:

this.createEmptyMovieClip(“jpgHolder”, this.getNextHighestDepth()); jpgHolder._xscale = 50; jpgHolder.loadMovie(“http://www.nathanderksen.com/book/afternoonShower.jpg”);

There is still one complication that needs to be dealt with. When images are loaded into a clip, the dimensions cannot be known until the image has completely loaded. In this case, a pre-loader is needed so that any code that relies on this information is called right after the image has finished loading. Preloaders are covered in detail in the next chapter.

Fully Qualified, Absolute, and Relative URLs

When passing a URL, you have the choice of three addresses to use:

A fully qualified address. It loads media from any URL regardless of whether it is on the same server as the main Flash movie, or whether it is on the same server but in a different directory. It begins with a declaration of the name of the server hosting the file in the form of http:// <servername>/ and includes the full path to where the file to be loaded is located on the specified server. The following are examples of fully qualified addresses:

http://www.nathanderksen.com/book/sampleAnimation.swf

http://images.apple.com/ipod/gallery/images/ipodgalleryfamily20051011.jpg

186

Controlling Movie Clips

An absolute address. It loads media from anywhere on the same server. It always starts with a leading slash, and includes the full path to where the file to be loaded is located on the same server. The following are examples of absolute addresses:

/book/sampleAnimation.swf

/ipod/gallery/images/ipodgalleryfamily20051011.jpg

A relative address. It assumes that the media to be loaded is in a fixed spot relative to where the main .swf file is located. The following are examples of relative addresses:

sampleAnimation.swf

images/ipodgalleryfamily20051011.jpg

Which address to use is generally up to you. Here are some things to consider in your decision:

If the media you are loading is on a different server, you have no choice but to use a fully qualified address.

It is preferable to use relative URLs because they are the same in your local development environment as they will be on a server. This means you can move the whole project to any location, and the links will all work.

Absolute URLs may be appropriate if the media you are loading is to be on the same server as your main movie, but is outside of your control. If you move your files to a new location, the references will not break.

Try It Out

Creating Thumbnail Buttons

This example extends the chapter’s first Try It Out example, adding the capability to place externally loaded images in the buttons.

1.Create a new Macromedia Flash document.

2.Click the first frame in the timeline, open the Actions panel, and type in the following ActionScript code:

#include “tryItOut_thumbnailButtons.as”

3.Select File Save As, name the file tryItOut_thumbnailButtons.fla, choose an appropriate directory, and save it.

4.Create a new Macromedia Flash document.

5.Name the file tryItOut_thumbnailButtons.as and save it in the directory containing the Flash project file.

6.Find the thumbnails folder in the Chapter 7 folder of the book source files and copy it to the same directory holding the .as and .fla files.

7.Type the following code into the new ActionScript file:

function createButton(buttonName:String, buttonLabel:String, ; buttonImage:String, parentClip:MovieClip, xPos:Number, yPos:Number) : Void

{

var newClip:MovieClip = this.createEmptyMovieClip(buttonName, ;

187