三、深度(Depth)
深度(Depth)僅僅需要一個數字描述,Flash Player 使
用這個數字來指定對象的層疊位置。所謂層疊是指一種顯示時的的遮蓋關系。深度值較大則顯示較前,深度值較小則顯示較后,較后的要被較前的遮蓋。深度具有可
比性但僅限于兄弟節點,所以同一父節點下的兄弟具有不同的深度,同時這個深度也描述了他們之間的層疊關系。屬于不同父節點的子節點可以有相同的深度,但他
們不具有可比性。
編輯環境下,Flash使用了圖層(Layer) 來組織對象。這時, Flash 并沒有給對象指定一個深度,只有當Flash 文檔在運行時 Flash Player根據用戶最初在編輯環境下的拖放情況來指定對象的深度。這里的圖層可以認為是同一父時間軸節點下子時間軸節點的集合。圖層和圖層之間不存在交集,而且圖層是一個動態的集合,隨著程序的運行,集合中的元素也會發生變化。Flash 也可以在運行時動態地創建時間軸,例如使用 attachMovie()、duplicateMovieClip()等語句,但必需以參數的形式給出要被創建的時間軸的深度。
對象在編輯環境下的拖放順序以及時間軸上圖層的層疊關系,用來幫助Flash 確定對象的深度。圖層在Actionscript中是不被引用的,所以在swf文件中也不會有圖層這個概念。在編譯時,圖層被分解為多個對象(多個時間軸),并且每一個對象都會被指定一個深度。當Flash 播放時,時間軸會讀取圖層中的內容,并根據和其他對象的相對位置關系指定它的深度。如果對象所在的圖層較高則獲得一個比較高的深度,如果對象所在的圖層較底則獲取一個較低的深度。與此同時,Flash也會為對象指定一個名稱,實現腳本對該對象的引用。深度概念也影響Flash 中對象的創建,在FileàPublish SettingàLoad Order 中可以設置對象被創建的順序,指定是由低深度到高深度(Bottom up)地創建,還是由高深度到低深度(Top down)地創建,Flash中的默認為前者。
Actionscript 還提供了一些與深度相關的方法和管理對象:
深度方法或深度管理對象
|
功能描述
|
返回值
|
MovieClip.attachMovie()
|
從庫中創建一個電影剪輯實例。
|
被創建的電影剪輯的引用
|
MovieClip.createEmptyMovieClip()
|
創建一個空的電影剪輯
|
被創建的電影剪輯的引用
|
MovieClip.createTextField()
|
創建一個文本框
|
無返回值
|
MovieClip.duplicateMovieClip()
|
創建一個電影剪輯的拷貝
|
被創建的電影剪輯的引用
|
MovieClip.getDepth()
|
返回電影剪輯的深度
|
深度數值
|
MovieClip.getInstanceAtDepth()
|
返回占據指定深度的電影剪輯
|
指定深度下電影剪輯的引用
|
MovieClip.getNextHighestDepth()
|
返回最高的可用深度
|
深度數值
|
MovieClip.removeMovieClip()
|
移除動態創建的電影剪輯
|
無返回值
|
MovieClip.swapDepths()
|
交換兩個電影剪輯的深度
|
無返回值
|
DepthManager Component
|
深度管理器
|
|
深度方法和功能描述
這里需要加以說明的是,SwapDepth()方
法可以把在不同深度的兩個對象進行深度交換。如果要實現這種交換有兩種方法:一是把兩個對象進行調換,即把上面的拿到下面,把下面的拿到上面,這是對對象
本身進行操作;二是直接更改對象的深度屬性,即直接修改指定對象深度的數值。但是如果使用后者顯然不是在交換深度而是在設置深度了。SwapDepth()方法是實現對象深度位置的交換而非設置深度??梢园焉疃壤斫鉃橐粋€容器,比如說是房子,如果兩個人要交換房子,那么必須是你搬過來我搬過去,而僅僅更換門牌是沒有什么用處的。所以深度是只讀的。另外,getDepth()方法可以很方便的獲取MovieClip、Button和TextField對象的深度數據。
另外,深度管理器(DepthManager)是一個專門對深度進行管理的Flash V2組件,它封裝了若干深度管理的方法:
DepthManager.createChildAtDepth():在指定深度處創建指定元件的子級。
DepthManager.createClassChildAtDepth():在該指定深度處創建指定類的對象。
DepthManager.createClassObjectAtDepth():在指定深度處創建指定類的實例。
DepthManager.createObjectAtDepth():在指定深度處創建一個對象。
DepthManager.setDepthAbove():移動實例到指定實例的深度之上。
DepthManager.setDepthBelow():移動實例到指定實例的深度之下。
DepthManager.setDepthTo():將實例移動到指深度。
四、深度區域:
在為對象指定深度時必須清楚地了解Flash在深度上的三個區域。在Flash 中,深度的范圍在-16384到2130690045之間,任何Flash的可視對象都不會超出這個范圍。在播放時,Flash把時間軸中的對象按照默認的設置進行加載。-16384到-1是深度的第一個范圍,在這個深度區域對象不可以使用腳本創建和移除,用于放置用戶在編輯環境下創建的對象,這里把它稱為時間軸區(Timeline)。接下來是0到1048575的深度范圍,在這個深度范圍內,對象可以使用腳本創建和移除,所以稱為動態區(Dynamic)。之后一個區域稱為保留區(Reserve),深度范圍在1048576和2130690045之間,可以放置MC但是不可以移除。
Flash的深度區域:
區域
|
深度范圍
|
特征
|
時間軸區
|
-16384 到 -1
|
主要用于放置Flash 編輯時的對象,且對象不可用腳本移除,但可以使用腳本創建。
|
動態區
|
0到1048575
|
實現運行時的動態創建、動態訪問和動態移除
|
保留區
|
1048576到2130690045
|
實現運行時的動態創建、動態訪問,但不支持使用腳本移除對象。
|
Flash 在動態區之前提供了時間軸區,用于放置編輯環境下時間軸中的對象。在編輯環境下,最底層的對象放置到區域的最深處——-16384。在通常情況下會從-16383這個深度開始,Flash依次向較高深度放置時間軸中的對象。
接下來是動態區,在這個區域可以放置那些可以動態創建和移除的對象。而且這個區域也符合一般人的使用習慣,因為它的深度是從0開始的,而開發者在創建對象時通常也會考慮這個范圍。在這個范圍可以獲得比較大的自由權,開發者可以使用腳本動態地創建和移除對象。如果對象不在動態區,那么首先可以把對象交換到動態區,然后再進行移除。
保留區可以理解為動態區的一個擴展,只是在保留區中無法使用腳本移除對象,對象在那個區域可以動態地被創建。在這個區域對象也可以使用swapDepth()方法交換到其它的深度區域。但保留區還是一個比較特殊的區域,因為那里的對象不可以被移除,而且深度高的有點離譜。在保留區Flash為對象提供了一定的存儲空間。
需要特別注意的是,Flash 在使用createEmptyMovieClip()方法創建的空MC時,深度的分配上幾乎沒有什么限制,深度可以指定在-999999999999以下或是999999999999以上。雖然這個深度已經超出了剛才討論的那個范圍。
五、時間軸刷新:
關于深度,可能會遇到一些另人混淆的問題,特別是動態區和時間軸區。當時間軸被刷新時,所有的對象將被重新創建。Flash 會掃描位于該時間軸的時間軸區域,并清除保存在這些深度上的對象。然后Flash 讀取時間軸上的數據并重新創建這些對象,但是通過動態方法創建的對象將被忽略。其中一個例子就是使用gotoAndPlay()返回播放已經播放過的幀,例如從第10幀返回到底5幀播放,這時Flash為了重新展示第5幀的內容必須刷新時間軸并完全重構第5幀的內容。但是使用動態方法創建的對象如果在時間軸刷新時被移除,那么這時并不被自動創建,除非程序給出。
很
明顯,這樣可能會引起一些問題。首先,這樣會失去在時間軸區域或是使用動態方法已經創建并交換到時間軸區域的對象。也就是在這中情況,不可以把使用動態方
法創建的對象交換到時間軸區域,否則在時間軸刷新時會丟失這些對象。在開發時為避免這種情況的發生,可以創建一個單幀停止的MC,這樣的MC可以是安全的,可以不必為時間軸刷新而擔憂。
另外一個問題是無法移除所需要移除的對象。其原因是由于使用深度交換方法把時間軸區的對象轉移到了非時間軸區,這樣在時間軸刷新時就無法清除該對象了,而且這次刷新還會創建一個新的該對象到時間軸區。這種情況也應該避免發生。
還有一個需要清楚的問題是場景(Scene)跳轉的問題。場景間的跳轉不會引起時間軸的刷新,也不會觸發其他一些特殊的事件。作為場景本身而言,它們是主時間軸的片段,當Flash被發布以后,這些場景便會整合到一起,變成單個的主時間軸。所以用戶在一個場景創建的對象,它仍舊可以在接下來的場景出現,當然也可以使用腳本使那些對象消失。
六、播放器執行順序:
在
深度問題上,還有一點比較容易被人們忽視。正如前面所提到的,深度也會影響到腳本的執行順序。事實上深度本身并不影響腳本的執行順序,但是深度卻與對象的
創建順序有關。一般我們都會認為,在同一時間軸上,首先被創建的對象會首先執行它所包含的腳本。另人感到奇怪的是,在默認的發布設置下,那些最晚被創建的
對象反而首先執行了EnterFrame事件中的腳本。在默認情況下對象從最底層開始被創建,這一點我們可以在Flash的發布選項中設置。幀腳本是按照它們被創建的順序執行的。這樣如果在bottom up 模式下,從技術角度而言,較低層的腳本反而較早執行,但是值得一提的是,EnterFrame事件中的腳本剛剛與之相反。
看來很有必要追究一下EnterFrame事件到底是怎樣的一個事件。EnterFrame事件隨著電影剪輯的幀速被持續地觸發??梢哉J為EnterFrame事件是在播放頭進入某一幀時觸發的一個事件,但是在EnterFrame事件中的代碼將先與幀腳本執行。但是,對象的創建和Flash的播放(對象狀態的改變過程)到底是怎樣一個關系呢?在Flash中第一幀的幀腳本和其它幀的幀腳本有著不同的行為。當運行一個Swf文
件時,它的第一幀將首先被創建,然后開始載入該文檔中的對象并拖入到舞臺,這個過程可以認為是一個初始化的過程。所以在這個過程中隨著對象的載入第一幀的
容量將不斷增大。這樣做的原因也是顯而易見的,只有當對象全部載入后,腳本才能執行,設想如果腳本所要操作的對象都不存在,那么腳本必然會發生錯誤。一旦
所有的對象載入完畢,除第一幀外的其它幀都將被一次性創建,并開始播放。這樣做的另外一個原因是,如果按照先創建,先播放的原則,那么必然導致不同電影剪
輯播放時步調的不一致。因為創建對象是需要時間的,特別是在網絡上,它還要有一個下載的過程。這里還要注意的是#initclip和#endinitclip中的代碼塊,它們通常定義在電影剪輯的第一幀,只要符號被定義且被編譯(電影剪輯符號定義了,但不一定都被編譯),那么就執行該代碼段,它用于電影剪輯的初始化,所以優先于其它腳本執行,并且僅執行一次,它的運行效果將作用到該剪輯的所有實例。
這樣,就可以得出,Flash的執行可以分成兩個過程。首先是對象的下載、創建和初始化,接下來是一個播放的過程。播放是一個對象狀態隨著幀速改變的過程,其狀態的兩個極端是存在與不存在。這樣在Flash的執行過程中,電影剪輯第一幀的腳本將首先被執行;然后是播放過程,其腳本執行的原則是EnterFrane事件腳本的執行先于幀腳本的執行。
七、圖層(Layer)、層級(level)和深度(depth)
通常人們會把圖層和層級混淆起來使用,但事實上它們是兩個完全不同的概念。時間軸可以以兩種方式獨立于主時間軸:電影剪輯(Movie Clip)和層級(Level)。這里所謂的獨立是指獨立的播放與停止。圖層(Layer),只在編輯環境下被看到,用于存放和組織在時間軸上的對象。它們僅僅只是在編輯環境下出現,當發布一個Flash文件時,這些圖層將被壓縮到同一個時間軸上。
層級(Level)位于一個獨立的時間軸上,用于存儲使用loadmovie方法加載的外部Swf文件。層級(Level)可以使用_level0, _level1, _level3, _leveln 對其進行引用。層級越高,就越接近觀察者,也就越容易被看到,這一點與深度是一致的。使用該方法加載的電影將貫穿電影的主時間軸。由于這個原因從外部加載電影的目的常常是為了加載某些聲音,因為聲音不會影響到原來電影的播放。
電影剪輯(Movie Clip)同樣是一個獨立的時間軸,但是電影剪輯位于庫(Library)中,并不是位于電影的外部。所以它與層級不同,如果需要的話,你可以在幀上創建一個電影剪輯的實例。 從庫中拖動一個電影剪輯到舞臺(Stage),那么就創建了該電影剪輯的一個實例,可以指定一個唯一的名稱對其進行引用。電影剪輯可以包含其它的電影剪輯,這就是通常所說的嵌套(nesting)。
深度(Depth)通常會用于swapDepth()和attachMovie()這些方法,用于指定電影剪輯的層疊順序。它可以被認為可視對象在時間軸上的層疊順序(Z-Order)。
這里還要指出的是 _root 和 _level0 的區別。_root 和_level0引用的并非同一個對象,它們是有差別的。_root 指代電影的主時間軸,如果一個電影有多個層級那么_root指代當前腳本正在執行的那個層級。例如:在層級n中的某個腳本包含了 _root,這時_root返回 _leveln,_root和_leveln才是等同的。
posted on 2008-06-16 15:41
七星重劍 閱讀(955)
評論(0) 編輯 收藏 引用 所屬分類:
Flash Scaleform GFx