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

Beginning ActionScript 2.0 2006

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

Chapter 27

}

}

public function zoomIn():Void

{

pTargetClip._rotation = 0; pTargetClip._xscale = pTargetClip._yscale = 2; pTargetClip._alpha = 2;

pTargetClip._visible = true; pTargetClip.onEnterFrame = function()

{

this._rotation -= 31; this._xscale *= 1.08; this._yscale = this._xscale; this._alpha = this._xscale; if (this._xscale >= 100)

{

this._rotation = 0; delete this.onEnterFrame;

}

}

}

}

4.Save the file.

5.Create a new Macromedia Flash document.

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

//Create a movie clip, then draw a square centered around the 0,0 point this.createEmptyMovieClip(“squareClip”, this.getNextHighestDepth()); squareClip.beginFill(0x000000, 100);

squareClip.moveTo(-100, -100); squareClip.lineTo(100, -100); squareClip.lineTo(100, 100); squareClip.lineTo(-100, 100); squareClip.lineTo(-100, -100); squareClip.endFill();

squareClip._x = 200; squareClip._y = 200;

//Create a second movie clip from the first one squareClip.duplicateMovieClip(“squareClip2”, this.getNextHighestDepth()); squareClip2._x = 400;

//Create new instances of the SpinEffect class for each clip

//to be animated.

var mySpinEffect = new SpinEffect(squareClip); mySpinEffect.zoomIn();

var mySpinEffect2 = new SpinEffect(squareClip2); mySpinEffect2.zoomOut();

688

Creating Custom Classes

7.Select File Save As, name the file tryItOut_spinEffect.fla, and save it in the same directory as SpinEffect.as.

8.Choose Control Test Movie to try it out.

How It Works

The SpinEffect class is composed of a movie clip that it uses for the animation. The SpinEffect class has-a movie clip, so composition is an appropriate approach to this class.

The class block itself is just the basic class statement. There is no extends MovieClip statement along with the class declaration, so no subclassing is being used:

class SpinEffect {

At the start of the class, a private property called pTargetClip is defined. This property will hold the movie clip to be animated, and forms the basis for this composition. Even though this class holds only one piece of data, it is still considered a composition:

private var pTargetClip:MovieClip;

The constructor takes in a single parameter, which is a handle to the movie clip to animate:

public function SpinEffect(targetClip:MovieClip)

{

pTargetClip = targetClip;

}

The zoomOut() method makes use of the movie clip that was passed in. It manipulates the scale, alpha, and rotation values of the movie clip to give the desired effect. The zoomIn() method is nearly identical; it just reverses the direction of the animation:

public function zoomOut():Void

{

pTargetClip._rotation = 0;

pTargetClip._xscale = pTargetClip._yscale = 100; pTargetClip._alpha = 100;

pTargetClip._visible = true; pTargetClip.onEnterFrame = function()

{

this._rotation += 31; this._xscale *= 0.92; this._yscale = this._xscale; this._alpha = this._xscale; if (this._xscale < 2)

{

this._visible = false; delete this.onEnterFrame;

}

}

}

689

Chapter 27

The process of creating a new instance of the custom class is the same as pretty much all the class creation code you have already seen throughout the book. Each instance of the effect uses a different movie clip and operates independently of the other:

var mySpinEffect = new SpinEffect(squareClip); mySpinEffect.zoomIn();

var mySpinEffect2 = new SpinEffect(squareClip2); mySpinEffect2.zoomOut();

Take a look at another example, where you create a queue class for loading data from a server.

Try It Out

Using Composition to Create a Data Queue

When loading data from a server, sometimes there is a need to break up a large request for data into multiple smaller requests. For instance, if you need to load a list of data records via XML, you can break up the data to keep the user interface more responsive. This queue class enables you to make multiple requests for data without worrying about how to manage loading data in sequence.

A queue is a type of array where data gets added onto one end and removed from the other, in the same way that you might line up for tickets at a movie theater. Each request is serviced in the order it is received. There is no queue data type in Flash, but that can be easily created using an array. This example uses composition to create a queue out of an array to load data from a server or from local files.

1.Create a new ActionScript document. Name it XMLQueueClass.as and save it in an appropriate folder.

2.Enter the following code into the file:

class XMLDataQueue

{

private var pDataQueue:Array; private var pIsLoadActive:Boolean; private var pXML:XML;

public function XMLDataQueue()

{

pDataQueue = new Array(); pIsLoadActive = false;

}

// Add a request to load a file

public function push(dataURL:String, callbackHandler:Function)

{

pDataQueue.push({url:dataURL, callback:callbackHandler});

if (pIsLoadActive == false)

{

pIsLoadActive = true; loadNextData();

}

}

// Load the next pending request in the list

690

Creating Custom Classes

private function loadNextData():Void

{

var parent:XMLDataQueue = this;

pXML = new XML(); pXML.ignoreWhite = true;

pXML.onLoad = function(status:Boolean)

{

parent.handleData(status);

}

pXML.load(pDataQueue[0].url);

}

//Get the data back from the currently loading request

//and pass the data to a user-specified callback function private function handleData(status:Boolean):Void

{

//Call the callback function for this request, and remove

//the request from the queue

if (status == true)

{

pDataQueue[0].callback(pXML, pDataQueue[0].url);

}

else

{

pDataQueue[0].callback(null, pDataQueue[0].url);

}

pDataQueue.shift();

// Make the next request, if there is still one in the queue if (pDataQueue.length > 0)

{

loadNextData();

}

else

{

pIsLoadActive = false;

}

}

}

3.Save the file.

4.Create a new Macromedia Flash document.

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

function dataHandler(returnData:XML, sourceURL:String):Void

{

var rootNode:XMLNode = returnData.firstChild; var numNodes:Number = rootNode.childNodes.length;

var photoId:String; var photoTitle:String;

691

Chapter 27

var photoSize:Number;

trace(“\nData loaded from: “ + sourceURL); for (var i=0; i < numNodes; i++)

{

photoId = rootNode.childNodes[i].attributes.id; photoTitle = rootNode.childNodes[i].attributes.title;

photoSize = Number(rootNode.childNodes[i].attributes.size); trace(“id: “ + photoId + “ title: “ + photoTitle + ;

“ size: “ + photoSize);

}

}

var myDataQueue:XMLDataQueue = new XMLDataQueue(); myDataQueue.push(“dataFile1.xml”, dataHandler); myDataQueue.push(“dataFile2.xml”, dataHandler); myDataQueue.push(“dataFile3.xml”, dataHandler);

6.Name the file tryItOut_xmlQueue.fla, and save it in the same directory as XMLDataQueue.as.

7.In your preferred text editor, create a file called dataFile1.xml. Enter the following XML markup in the file:

<?xml version=”1.0”?> <photos>

<photo id=”aStudyInSpeed” title=”A Study In Speed” size=”123” /> <photo id=”aStudyInTexture” title=”A Study In Texture” size=”321” /> <photo id=”beachAbstraction” title=”Beach Abstraction” size=”231” /> <photo id=”buntzenFog” title=”Buntzen Fog” size=”213” />

</photos>

8.In your preferred text editor, create another file called dataFile2.xml. Enter the following XML markup in the file:

<?xml version=”1.0”?> <photos>

<photo id=”christmasFrost” title=”A Study In Speed” size=”323” /> <photo id=”fishingAtSunset” title=”Fishing At Sunset” size=”121” /> <photo id=”forestPath” title=”Forest Path” size=”221” />

<photo id=”galianoSunset” title=”Galiano Sunset” size=”112” /> </photos>

9.In your preferred text editor, create a third file called dataFile3.xml. Within this file, place the following XML markup:

<?xml version=”1.0”?> <photos>

<photo id=”granvilleIsland” title=”Granville Island” size=”113” /> <photo id=”greenLakeInRed” title=”Green Lake in Red” size=”143” /> <photo id=”heavenlyLight” title=”Heavenly Light” size=”131” /> <photo id=”liquidSun” title=”LiquidSun” size=”213” />

</photos>

10.Choose Control Test Movie to try it out.

692

Creating Custom Classes

How It Works

With this example, it is less clear as to whether an is-a or a has-a relationship exists. A queue is-a type of array; however, this queue is designed for server communications and contains more functionality than just array management. The array is thus just one element of a composition that also includes the XML class. In this light, the XMLDataQueue class has-an array and is well-suited for composition.

The private properties store an array to be used for creating the queue, plus an XML object to handle the actual data loading. The pIsLoadActive property is used to stop checking the queue if there are no requests left to load:

private var pDataQueue:Array; private var pIsLoadActive:Boolean; private var pXML:XML;

The constructor sets initial values to the properties:

public function XMLDataQueue()

{

pDataQueue = new Array(); pIsLoadActive = false;

}

The push() method is the only public method. This method adds a request to the end of the queue. If the data loader is idle because the queue was previously empty, the loader is started back up:

public function push(dataURL:String, callbackHandler:Function)

{

pDataQueue.push({url:dataURL, callback:callbackHandler});

if (pIsLoadActive == false)

{

pIsLoadActive = true; loadNextData();

}

}

The loadNextData() method grabs the request that is currently at the start of the queue and loads the requested file. The first line where parent is declared allows handleData() to be properly called from this class instance. Without it, handleData() cannot be called from within the onLoad() function:

private function loadNextData():Void

{

var parent:XMLDataQueue = this;

pXML = new XML(); pXML.ignoreWhite = true;

pXML.onLoad = function(status:Boolean)

{

parent.handleData(status);

}

pXML.load(pDataQueue[0].url);

}

693

Chapter 27

The handleData() method deals with the data returning from the server. When the XML returns, handleData() passes that data to the function assigned to handle this request. The request is then removed from the queue and the next request is processed:

private function handleData(status:Boolean):Void

{

if (status == true)

{

pDataQueue[0].callback(pXML, pDataQueue[0].url);

}

else

{

pDataQueue[0].callback(null, pDataQueue[0].url);

}

pDataQueue.shift();

if (pDataQueue.length > 0)

{

loadNextData();

}

else

{

pIsLoadActive = false;

}

}

Taking a look at the code within the Actions panel of the FLA file, you see that the dataHandler() function deals with actually doing something with the data returned from the server. If you are not sure about how to parse XML data, return to Chapter 21.

function dataHandler(returnData:XML, sourceURL:String):Void

{

var rootNode:XMLNode = returnData.firstChild; var numNodes:Number = rootNode.childNodes.length;

var photoId:String; var photoTitle:String; var photoSize:Number;

trace(“\nData loaded from: “ + sourceURL); for (var i=0; i < numNodes; i++)

{

photoId = rootNode.childNodes[i].attributes.id; photoTitle = rootNode.childNodes[i].attributes.title;

photoSize = Number(rootNode.childNodes[i].attributes.size); trace(“id: “ + photoId + “ title: “ + photoTitle + ;

“ size: “ + photoSize);

}

}

Finally, an instance of the XMLDataQueue class is created and requests are made for the data files. If this were actually calling dynamic data on a server, you would instead use the URL to get to the JSP, ASP, PHP, or servlet page that actually returns the data:

var myDataQueue:XMLDataQueue = new XMLDataQueue();

694

Creating Custom Classes

myDataQueue.push(“dataFile1.xml”, dataHandler); myDataQueue.push(“dataFile2.xml”, dataHandler); myDataQueue.push(“dataFile3.xml”, dataHandler);

Summar y

This chapter explored the process of creating custom classes. Some of the things that you learned include the following:

A custom class allows you to organize and package your own code in a way that makes code cleaner and re-use significantly easier.

Classes must be placed in their own .as files with the same name as the class itself.

A constructor is a special class method that is called when an instance of the class is created using the new operator. The constructor calls code that should run at the instance’s startup.

Public properties and methods are available to anyone who uses your class. Private properties and methods can be called only from within the class itself.

Properties and methods are defined in the same way as variables and functions, only they are preceded with either the public or the private keyword and they exist within a class block.

Public properties should be implemented using getter and setter functions. The actual internal property should not be made public.

Subclassing is used to extend other classes, by allowing a class to inherit another class’s methods and properties, and then adding or modifying them. Subclassing is not actually recommended for extending the functionality of the classes built into Flash.

Classes with static methods are a good way to provide a library of functionality. Static methods do not require the class to be instantiated to be used.

Composition allows for class functionality to be extended in a cleaner way than subclassing allows. Composition involves one class containing or being composed of one or more other classes.

Exercises

1.By just looking at the following properties, which of the property declarations are valid, which are invalid, and why?

a.var myProperty:String;

b.public var myProperty2;

c.static public var myProperty3:String;

d.private myProperty4:Boolean;

e.private var myProperty5:Boolean = false;

f.public var myProperty6:Boolean = “true”;

695

Chapter 27

2.Assume the following class definition:

class TestClass

{

private var pMessageText:String; public var altMessage:String = “”;

function TestClass(initialMessage:String)

{

pMessageText = initialMessage;

}

public function get messageText():String

{

return pMessageText;

}

public function set messageText(newMessage:String):Void

{

pMessageText = newMessage;

}

public function getAlternate():String

{

return altMessage;

}

private function replaceText(fromText:String, toText:String):Void

{

pMessageText = pMessageText.split(fromText).join(toText);

}

public function removePunctuation():String

{

replaceText(“.”, “”); return pMessageText;

}

}

Also assume the following class instantiation:

var myTestClass:TestClass = new TestClass(“The quick brown fox.”);

Without trying the preceding code, what is the result of running each of the following statements?

a. myTestClass.messageText = myTestClass.messageText + ;

“ Jumped over the lazy dog.”;

b.

c.

d.

e.

f.

g.

trace(myTestClass.messageText);

trace(myTestClass.pMessageText);

myTestClass.replaceText(“.”, “”);

myTestClass.removePunctuation();

trace(myTestClass.messageText);

myTestClass.altMessage = “Foo”;

696

Creating Custom Classes

h.

i.

j.

trace(myTestClass.alternate);

trace(myTestClass.altMessage);

trace(myTestClass.getAlternate());

3.Create a class for managing the data for a photo viewer application. It should consist of an array to hold the data about each photo. Each array element should contain the following anonymous object:

var tempObject:Object = new Object(); tempObject.id = “photo1”; tempObject.name = “Photo 1”;

tempObject.description = “The quick brown fox 1”; tempObject.thumbnailURL = “photo1Thumbnail.jpg”;

tempObject.fullSizeURL = photo1FullSize.jpg”; tempObject.size = 123;

tempObject.visited = false;

pPhotoArray.push(tempObject);

The class should have the following properties and methods:

A method called addData() that takes an id, a name, a description, a URL for a thumbnail image, a URL for a full-size image, and the size of the image. It should create an anonymous object, assign these properties to the object, and then add it to the array.

A method called getDataById() that takes a string, searches through the array for a data entry that has that ID, and then returns that whole entry.

A method called getDataByIndex() that takes a number and returns the data entry at that position in the array.

A method called setVisited() that accepts a number indicating the array position to modify, sets the visited attribute to true, and then updates a private property that keeps track of the number of visited photos.

A read-only property called numPhotos that returns the size of the photo array.

A read-only property called numVisited that returns the number of photos that have their visited properties set to true.

A method called toString() that returns loops through each array element and prints out each attribute name and value. Hint: Use “\n” in a string to force a line break.

4.Extend the final Try It Out thumbnail_v3 exercise to allow for a tool tip text description to show up under the icon when the mouse is over the thumbnail button.

You might want to use the MovieClip.createEmptyMovieClip() method to create a movie clip holder in the constructor and then use MovieClip.createTextField() to place an empty text field in that movie clip.

The tool tip text should be set via a public property accessed using a pair of getter and setter methods. The setter should assign the text to the text field and then should apply any desired text formatting. You might elect to use the drawing API to draw a box around the text.

Use the drawThumbnail() method to position, show, and hide the text field depending on the thumbnail state.

697