ActionScript 3.0動畫基礎-4

作者: egoldy

性質: 翻譯

閱讀次數: 19636

發表時間: 2007-07-08 15:22:01


山东20选5最新开奖结果 www.vyjto.com 聲明: 此文章為未出版的keith peters的ActionScript 3.0 making things move中文版樣章。為書中的第二章。webstudio會在中文版出版之際,友情提供論壇forum支持。轉載請注明出處,謝謝!


接上一篇.....


2.6顯示列表display list

在AS3之前,你可以在一個Flash影片中創建不同數量類型的可視對象,包括影片剪輯,圖形元件,按鈕,文本域,位圖,組件,和基本的圖形。這 些對象實際上并沒有被組織成一定的層次結構,并且他們都有各自不同的創建,銷毀,和操作的方法。舉例來說,影片剪輯可以通過貼加(attach),復制, 或通過動態創建放置在舞臺上。文本域可以動態的創建或是在Flash IDE中創建。當你在創建位圖,視頻,組件和其它的內容時,他們看起來象是在不同的平臺上創建的,然后被堆放在Flash中,并強行讓他們在一直工作。
在AS3中,這些不同的對象現在都被統一規化在一個地方。你所看到的舞臺上的任何對象都由DisplayObject類的擴展所創建的?;恢紙?度講,所有的對象都是一個大家庭的一部分,他們都有著相同的基本行為,根據這點你可以知道怎樣創建他們,把他們放在舞臺上,銷毀他們,并在舞臺上操作他 們。
現在創建一個精靈(sprite),一個影片剪輯,或一個文本域的方法非常的相似。實際上,所有的顯示(display)對象現在都使用相同的方法創建,這種方法也是你創建其它任何類型對象的方法,那就是使用new操作符。為了驗證這一點,下面給出如何創建這幾個對象:

var  myTextfield:TextField  =  new  TextField();
var  myMovieClip:MovieClip  =  new  MovieClip();
var  mySprite:Sprite  =  new  Sprite(); 

這種方式是不是更簡單呢?
你已看過前面的范例了,如果你已經創建一個影片剪輯或是精靈(sprite),現在你可在那些對象里繪制內容,如下:

mySprite.graphics.beginFill(0xff0000);
mySprite.graphics.drawCircle(0,  0,  
40); mySprite.graphics.endFill(); 

但是如果只是象上面那樣做了,你可能看不到任何內容。這就是我們將要討論的顯示列表(display list)。“display list”術語是一個新增的,但是如果你使用Flash已經有一段時間了,它不應當是一個完全陌生的概念。把你影片中的所有可視對象想為一個樹形。樹的最 底部是舞臺,它默認狀態就是可視的。在舞臺上,你可能還有幾個影片剪輯或其它類型的可視對象(文本域,圖形等等)。當你將他們加入到舞臺上時,他們也會變 成可視的。在那些影片剪輯內部可能還會有其它的影片剪輯或其它的可視對象,并且在其它的內部也可能會有。這就是最基本的顯示列表(display list)。

顯示列表(display list)工作方式是AS2與AS3中最大的不同之處。在AS2中,當你通過attach命令或是使用createEmptyMovieClip創建一個 影片剪輯, 它必須要在創建時指明它將放在哪里。另外一點,影片剪輯被創建后,被放置在一個指定位置的列表中,那就是它所要留的地方。移除影片剪輯時,沒有辦法在位置 列表中改變它的位置或是讓它從列表中徹底銷毀。
在AS3中,當你創建一個新的影片剪輯,精靈,或其它的顯示(display)對象時,它不會自動的加入到顯示列表(display list)中。注意在剛剛給出的sprite范例中,當創建精靈(sprite)時沒有提到過父級(parent)或是深度(depth)。它們是可以存 在的但并不是在顯示列表(display list)中被操作的。
如果從字面意義上理解“stage”(舞臺),你可以想象那些對象就是幕后的演員,收起翅膀,懸在舞臺的上空,或是想象為趴在地底下。你不能看見他們,但是他們都在那里,繁忙的準備著他們的入場,到那時他們將跳上舞臺并且真實的顯示出來。
現在為止,我們已經使用了樹的比喻和一個劇院的比喻---還有其它的比喻嗎?我們也可以將顯示列表(display list)想象為一個大家庭,一個這樣的parent/child/sibling家族關系。當你加入某些東西到顯示列表(display list)中,對象將被加入到父級(parent)中,那么新加入對象就是父級的兒子。如此這樣,當你增加一個對象到列表中時它是有理性的。你需要使用 addChild方法來完成。
你的文檔類(document class)就象是一個樹的根(或是所有可視對象的偉大的父親,如果你愿意)。它是自動可視的,然后你開始為它加入孩子。因此,如你看到的之前的范例,要 使精靈(sprite)或其它顯示對象(display object)可視,傳遞給它一個新創建的精靈(sprite):

var  mySprite:Sprite  =  new  Sprite();
mySprite.graphics.beginFill(0xff0000);
mySprite.graphics.drawCircle(0,  0,  40);
mySprite.graphics.endFill();
addChild(mySprite); 

如果你試一試這些,將這些代碼放在之前類結構中的init函數中。注意它將放置在原點0,0上。你可以通過調整x,y屬性來改變它的位置?;掛⒁獾氖欽?里沒有提到深度(depth),深度如同當我們在AS2中創建影片剪輯或使用attach貼加他們的過程。雖然深度管理大部分情況下是自動的,但仍有加入 子對象的方法可以加入到指定的深度或改變它的深度,這些在我們需要的時候我們會講到。
要從一個顯示列表(display list)中移除掉一個對象,調用removeChild方法,傳遞一個子對象的引用。第一個關鍵的地方是要意識到移除一個子對象并不是銷毀它!它會保持 與你移除它之前一樣的狀態而存在的。并且在將它加入回顯示列表(display list)時仍保持原有的狀態?;恢紙嵌冉?,在AS2中,如果你已經在子對象中繪制了一些圖形,或載入了些外部內容到子對象中,當你要將它加回到顯示列表 (display list)中時,將不得不重新繪制或重新載入那些內容。
第二個關鍵的地方要意識到當你將一個子對象加回到列表中時,你可以自由的將它放在任何地方。這被稱為重設父級(reparenting)并且是 令人興備的(至少對我是這樣)。你可以從一個影片剪輯移除一個對象并將它貼加到另一個對象中,當你移除它時它會保持原有的狀態,這在之前版本中是不可能 的。實際上,你不需要移除它,因為一個子對象只能有一個父級,將它加入另一個父級會自動先從原來的父級移除。
The following class demonstrates reparenting:
下面的類演示重設父級

package  {
import  flash.display.Sprite;
import  flash.events.MouseEvent;

public  class  Reparenting  extends  Sprite  {
private  var  parent1:Sprite;
private  var  parent2:Sprite;
private  var  ball:Sprite;
public  function  Reparenting()  {
init();
}
private  function  init():void  {
parent1  =  new  Sprite();
addChild(parent1);
parent1.graphics.lineStyle(1,  0);
parent1.graphics.drawRect(-50,  -50,  
100,  100); parent1.x  =  60;
parent1.y  =  60;

parent2  =  new  Sprite();
addChild(parent2);
parent2.graphics.lineStyle(1,  0);
parent2.graphics.drawRect(-50,  -50,  100,  100);
parent2.x  =  170;
parent2.y  =  60;

ball  =  new  Sprite();
parent1.addChild(ball);
ball.graphics.beginFill(0xff0000);
ball.graphics.drawCircle(0,  0,  40);
ball.graphics.endFill();
ball.addEventListener(MouseEvent.CLICK,  onBallClick);
}

public  function  onBallClick(event:MouseEvent):void
{
parent2.addChild(ball);
}
}
}

這個類創建了三個精靈(sprite):parent1,parent2,和ball。Parent精靈直接加到顯示列表(display list)中,并且方塊被繪制在它們的內部。Ball精靈(sprite)被加入到parent1中,因此現在它存在于顯示列表(display list)中并是可視的。
當小球被點擊時,它會加入到parent2中。注意這里沒有改變它的x,y位置的代碼。它會發生移動是因為它在位置不同的精靈(sprite)中?;褂幸⒁獾牡本?sprite)在移除和加入的過程中,動態繪制的圓形會始終保持著。

2.6.1子類中的顯示對象(display object)

在前面,你已經學習了在創建文檔類(document class)時精靈(sprite)和影片剪輯的子類。這些類的子類還有許多的其它用途。
首先,你可能在想,因為在AS3中attachMovieClip不在可用了,那如何在影片運行時將Flash CS3 IDE庫中的影片剪輯元件放入到影片中呢?答案是使用一個擴展了精靈(sprite)或影片剪輯的子類。雖然我努力的在創建SWFs影片時不去使用任何的 工具,但我們還是要回到Flash IDE中來解釋它。
通過下面的例子是最好的說明:
1.  創建一個新的FLA,然后在舞臺上繪制一些內容。
2.  選中內容按下F8將其轉換為元件。
3.  在轉換元件的對話框中,輸入元件的名稱,并選擇元件類型為影片剪輯(MovieClip)。
4.  選擇為ActionScript導出。
在這一點上,在之前版本的Flash中,你將獲得一個自動生成的鏈接ID,你也可以選擇輸入一個類。
在Flash CS3中,鏈接ID文本域被禁止了,類文本域強制要求輸入并且添充了一個默認值。它也是一個新的文本域,基于類,它預置的是flash.display.MovieClip。你可以將它改為擴展影片剪輯或精靈(sprite)的其它類。
輸入你想要的類的名稱。不用擔心你還沒有創建這個類。然后點擊“OK”。這里會比較有趣。因為Flash不能找到你指定名稱的類,它將在編譯時自 動生成一個類。這并不意味著你可以找到Flash自動創建的一個ActionScirpt類,但是它會在你的SWF中以字節代碼(bytecode)的形 式創建一個基于精靈(sprite)或影片剪輯的新類。這個類實際上不能象擴展其它基礎類的子類一樣,但是它將會鏈接到你庫中的元件。

現在,假設你在剛才說到的對話中輸入的類名為Ball。在你的文檔類(document Class),或在時間線上,你可以書寫如下代碼:

var  ball:Ball  =  new  Ball();
addChild(ball); 

這樣庫中的元件應會在舞臺上被創建,就是象以前AS2中的attachMovie方法。
如果你想將庫中的影片剪輯內容貼加到影片中,這是一個非常好的方法。但是比只是簡單的接受自動生成類的更好方法是,你可以指定一個自已編寫的真實的類路徑,可以為你的元件加入一些函數定義。現在讓我們跳出Flash IDE,回到下一個范例的類中來。
現在,我們將重新來看前面剛剛給出的重設父級(reparenting)的范例,那里的一些復制可以被簡化為另一個類。在那個范例中,我們創建了一個名為parent1的精靈并在它的內部繪制了一個盒子如下代碼:

parent1.graphics.lineStyle(1,  0);
parent1.graphics.drawRect(-50,  -50,  100,  100);

我們接著創建了另外一個精靈(sprite),parent2,在它的內部也用同樣的代碼繪制了同樣的盒子。盡管這是一個很簡單的例子,但是它可以清晰的 顯示出精靈的子類是怎樣應用的。首先,我們創建一個擴展精靈(sprite)名為ParentBox 的類。在這個類中,我們編寫編制盒子子代碼。

package  {
import  flash.display.Sprite;

public  class  ParentBox  extends  Sprite  {
public  function  ParentBox()
{
init();
}
private  function  init():void
{
graphics.lineStyle(1,  0);
graphics.drawRect(-50,  -50,  100,  100);
}
}
} 

然后我們將告訴類創建兩個ParentBox即可,而不再是兩個精靈(spirte)了。

package  {
import  flash.display.Sprite;
import  flash.events.MouseEvent;

public  class  Reparenting2  extends  Sprite  {
private  var  parent1:ParentBox;
private  var  parent2:ParentBox;
private  var  ball:Sprite;

public  function  Reparenting2()  {
init();
}
private  function  init():void  {
parent1  =  new  ParentBox();
addChild(parent1);
parent1.x  =  60;
parent1.y  =  60;

parent2  =  new  ParentBox();
addChild(parent2);
parent2.x  =  170;
parent2.y  =  60;

ball  =  new  Sprite();
parent1.addChild(ball);
ball.graphics.beginFill(0xff0000);
ball.graphics.drawCircle(0,  0,  40);
ball.graphics.endFill();
ball.addEventListener(MouseEvent.CLICK,  onBallClick);
}
public  function  onBallClick(event:MouseEvent):void
{
parent2.addChild(ball);
}
}
} 

作為parentBox的實例,他們仍是精靈(Sprite),因此可以在它們中加入子對象。它們也可以使用新的繪制圖形的init方法。這是一個很小的例子,但是希望你能夠理解它,當你繼續向下看這本書時,你會看到許多更為復雜的范例。
你也許想要針對此例加入一個Ball類,這樣做不能夠在減少你的復制操作了,但是會使你的類變得更為復雜,一個比較好的主意是將某些可分離的功能 定義成不同的類,而不應是把任何不論有多小的東西都放入到一個單獨的類中。這種方式也是最值得的推薦的。實際上,在接下本書的內容中,你很快就可以創建一 個你需要用到的Ball類了。

2.7用戶交互操作

最后,我們來看用戶交互,可能這就是你要閱讀本書的原因之一。除此之外,如果本書沒有使用交互或在影片中的一些動態輸入,你也許要使用的就是補間(tween)了。
實際上,我們在前面的章節上并不是一點也沒有討論這部分的內容。用戶交互是基于用戶事件,它們產生于鼠標事件和鍵盤事件。讓我們快速的過一遍各種用戶事件和它們的處理者(handler)。

2.7.1鼠標事件

鼠標事件在AS3中已經發生了激動人心的改變。在AS2中,影片剪輯自動的偵聽所有的鼠標事件。現在任何對象都明確的加入自身做為一個偵聽者。另 外,在AS3中要響應鼠標事件,需要鼠標的光標停放在可視的顯示對象(display object)內容上。這一點不同于AS2,在AS2中的mouseUp,mouseDown和mouseMove對于任何影片剪輯都會響應,而不管鼠標 的光標是否已經定好位置。AS3中的mouseUp和mouseDown事件現在等同于AS2中的onPress和onRelease。
鼠標事件的名稱被定成字符串,這在前面的內容中我們已經提到過,最好的方法是使用MouseEvent的屬性以保證不會出錯。下面是MouseEvent類中可用的鼠標事件:
CLICK
DOUBLE_CLICK
MOUSE_DOWN
MOUSE_MOVE
MOUSE_OUT
MOUSE_OVER
MOUSE_UP
MOUSE_WHEEL
ROLL_OUT
ROLL_OVER
這些屬性自身名稱就是很好的解釋。如果要感覺一下他們,你可以創建和編譯下面的類,它將trace出精靈(sprite)上發生的每一個鼠標事件。

package  {
import  flash.display.Sprite;
import  flash.events.MouseEvent;

public  class  MouseEvents  extends  Sprite  {
public  function  MouseEvents()  {
init();
}
private  function  init():void
{
var  sprite:Sprite  =  new  Sprite(); addChild(sprite);
sprite.graphics.beginFill(0xff0000); sprite.graphics.drawCircle(0,  0,  
50); sprite.graphics.endFill();
sprite.x  =  stage.stageWidth  /  2;
sprite.y  =  stage.stageHeight  /  2;

sprite.addEventListener(MouseEvent.CLICK,  onMouseEvent);
sprite.addEventListener(MouseEvent.DOUBLE_CLICK, onMouseEvent);
sprite.addEventListener(MouseEvent.MOUSE_DOWN, onMouseEvent);
sprite.addEventListener(MouseEvent.MOUSE_MOVE, onMouseEvent);
sprite.addEventListener(MouseEvent.MOUSE_OUT, onMouseEvent);
sprite.addEventListener(MouseEvent.MOUSE_OVER, onMouseEvent);
sprite.addEventListener(MouseEvent.MOUSE_UP, onMouseEvent);
sprite.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseEvent);
sprite.addEventListener(MouseEvent.ROLL_OUT, onMouseEvent);
sprite.addEventListener(MouseEvent.ROLL_OVER, onMouseEvent);
}
public  function  onMouseEvent(event:MouseEvent):void
{
trace(event.type);
}
}
}

注意,這個類對每一種事類型使用了同一個處理者(handler),只是簡單的trace出被發送出來的事件類型。

2.7.2鼠標位置

除了鼠標事件,還有兩個重要的屬性是可能的,它們是來自文檔類(document class)或其它顯示對象(display object)用來檢測當前鼠標光標的位置:mouseX和mouseY。注意他們是影片剪輯的屬性,返回是鼠標相對于剪輯注冊點的位置。例如,如果你有 一個名為sprite的精靈在舞臺上的位置為100,100,鼠標光標的位置在150,250,你會得到下面的結果:
mouseX is 150.
mouseY is 250.
sprite.mouseX is 50.
sprite.mouseY is 150.
注意影片剪輯是如何得出鼠標光標在它自身上的位置的。

2.7.3鍵盤事件

鍵盤事件是另一部分在AS3中被整理的部分。例如,在AS2中,影片剪輯自動的偵聽鍵盤事件,但是它們只在特點的環境下才會響應事件。因些最好的 辦法是加入一個影片剪輯做為偵聽者,但是當影片接受多個事件而不只是單單接收鍵盤事件時,這種方法會失效。接著,AS2組件架構的一大部分是用來處理鍵盤 的交互---關系到Flash播放器底層的架構:tab管理,焦點管理,文本域中的回車和tab鍵,等等。
現在我們說情況要好的很多
鍵盤事件的名稱,就象鼠標事件一樣,被定義成字符串,但他們仍是KeyboardEvent類的屬性。他們只有兩個:
   KEY_DOWN
   KEY_UP
你可以在一個指定的對象上偵聽鍵盤事件,就象我們前面講到的偵聽鼠標事件一樣。為了做到這一點,然而,你需要先使對象獲得焦點以使它可以捕獲那些事件。你可以象下面這樣書寫:
stage.focus  =  sprite;
而在許多案例中,只記得偵聽鍵盤事件卻忽視的它的焦點。要做到這一點,你可以直接在舞臺上偵聽鍵盤事件。下面是一個范例示范:

package  {
import  flash.display.Sprite;
import  flash.events.KeyboardEvent;

public  class  KeyboardEvents  extends  Sprite  {
public  function  KeyboardEvents()  {
init();
}
private  function  init():void  {
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboardEvent);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyboardEvent);
}
public  function  onKeyboardEvent(event:KeyboardEvent):void  {
trace(event.type);
}
}
} 

2.7.4鍵盤代碼

通常,你想知道的并不只是一個鍵子被按下去或放出,而是想知道它是哪一個鍵子。有兩種方法可以讀取鍵盤事件函數中的信息。
在之前我們討論事件的過程中,我說過一個事件處理者(handler)接收傳過來的一個事件對象,這個事件對象中包含著剛剛發生的事件的數據信息。在一個鍵盤事件中,有兩個屬性與事件中的按鍵有關:charCode和keyCode。
charCode屬性給出的是真實的描述鍵子的字符。例如,如果用戶在鍵盤上按下“a”鍵,charCode將包含這個字符串“a”。如果用戶同時也按下了Shift鍵,charCode將包含的是“A”。
KeyCode包含的是描述按下鍵子的物理鍵值。如果一個用戶按下“a”鍵,keyCode將包含數值65,會忽視其它同時按下的按鍵。如果用戶同時按下Shift和“a”,你需要兩個鍵盤事件:一個是Shift(keyCode 16)和另一個是“a”(65)。
flash.ui.Keyboard類也有一些屬性可用于一些數字鍵,因此你不需要記住它們,例如,Keyboard.SHIFT 等于數值16,因些你可檢測keyCode是否等于Keyboard.SHIFT來發現Shift鍵是否被按下。這一章中的最后一個例子示范如下:

package  {
import  flash.display.Sprite;
import  flash.events.KeyboardEvent;
import  flash.ui.Keyboard;

public  class  KeyCodes  extends  Sprite  {
private  var  ball:Sprite;

public  function  KeyCodes()  {
init();
}
private  function  init():void  {
ball  =  new  Sprite();
addChild(ball);
ball.graphics.beginFill(0xff0000);
ball.graphics.drawCircle(0,  0,  40);
ball.graphics.endFill();
ball.x  =  stage.stageWidth  /  2;
ball.y  =  stage.stageHeight  /  2;
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboardEvent);
}
public  function  onKeyboardEvent(event:KeyboardEvent):void  {
switch(event.keyCode)  {
case  Keyboard.UP  :
ball.y  -=  10;
break;

case  Keyboard.DOWN  :
ball.y  +=  10;
break;

case  Keyboard.LEFT  :
ball.x  -=  10;
break;

case  Keyboard.RIGHT  :
ball.x  +=  10;
break;

default:
break;
}
}
}
}

還一點需要知道的是當你在Flash創作環境中測試你的影片時,Flash IDE會偵聽一些鍵子來操作IDE自身。如Tab鍵,所有的功能鍵,和一些指定了快捷鍵的菜單,這些鍵子不會在你的測試影片中被接收。你可以通過選擇控制 菜單(control>Disable Keyboard Shortcuts)然后選擇禁止快捷鍵來解決。測試時就象真正工作在瀏覽器中一樣。

總結

這一章覆蓋了所有關于ActionScript動畫所需要基礎。你現已經知道了幀循環,事件,偵聽者,處理者,和顯示列表。我也介紹了類,對象和 基本的用戶交互。這是許多有用的資料!如果有些地方還有點模糊不用擔心。當進入到指定的技術內容時,我會盡量詳細講解它們,并且你可以隨時回到這里,鞏固 任何概念。至少,現在你已經熟悉了這些術語和概念,你可以準備繼續向前了。

<全文完>

 

討論此教程

關于我們

萬博思圖(北京)信息技術有限公司,專業的flash,flex開發團隊,5年經驗。公司致力于互聯網上的業務的開展,對于互動網站行銷,互聯網應用程序開發有成熟的解決方案。我們關注互聯網市場動態,關注新技術,更注重在新的領域不斷探索發現。
萬博思圖業務內容主要包括企業品牌Flash網站開發,企業形象宣傳Flash設計,動畫,多媒體演示,Flex企業級應用程序開發,擁有眾多成功案例,歡迎來電咨詢。
COPYRIGHT BY WEBSTUDIO INTERACTIVE DESIGN Co.,Ltd. ALL RIGHTS RESERVED.
公司地址: 北京市朝陽區朝外SOHO D 座727室 郵編: 100026 EMAIL: [email protected]
電話: 010-59070059 / 010-86390986-802  手機: 13693660520 傳真: 010-59070059-801
京公網安備:110108006741      京ICP備:05013074號-1
王先生