動畫和計時系統概觀
更新:2007 年 11 月
本主題說明計時系統如何使用動畫、Timeline 和 Clock 類別建立屬性的動畫。
必要條件
若要了解這個主題,您應該要能夠使用 WPF 動畫建立屬性的動畫,如動畫概觀中所述。這也有助於熟悉相依性屬性;如需詳細資訊,請參閱相依性屬性概觀。
時刻表和時鐘
動畫概觀中會說明 Timeline 如何代表示時間區段,以及動畫為何是一種會產生輸出值的 Timeline。Timeline 本身不會做其他的事,只是描述一個時間區段。真正在執行工作的是時刻表的 Clock 物件。同樣的,動畫並不真的是在建立屬性的動畫:動畫類別只負責描述計算輸出值的方式,真正會計算動畫輸出並將該輸出套用至屬性的乃是 Clock。
Clock 是一種特殊的物件,它可以維護 Timeline 的時間相關執行階段狀態。它以三個位元提供了動畫和計時系統最重要的資訊:CurrentTime、CurrentProgress 和 CurrentState。Clock 會使用其 Timeline 所描述的 Duration、RepeatBehavior、AutoReverse 等計時行為,來決定它目前的時間、進度和狀態。
在大部分情況下,您的時刻表會自動建立 Clock。當您使用 Storyboard 或 BeginAnimation 方法建立動畫時,您的時刻表會自動建立時鐘,並將動畫套用至它們的目標屬性。您也可以使用 Timeline 的 CreateClock 方法,明確建立 Clock。MediaTimeline.CreateClock方法會針對呼叫它的 Timeline 建立適當類型的時鐘。如果 Timeline 包含子時刻表,也會為子時刻表建立 Clock 物件。產生的 Clock 物件會依照來源 Timeline 物件樹狀目錄的結構,排列在樹狀目錄中。
不同類型的時刻表有不同類型的時鐘。下表針對其中幾種不同的 Timeline 類型顯示相對應的 Clock 類型。
時刻表類型 |
時鐘類型 |
時鐘用途 |
---|---|---|
Animation (繼承自 AnimationTimeline) |
產生相依性屬性的輸出值 |
|
處理媒體檔案 |
||
分組並控制它的子 Clock 物件 |
||
分組並控制它的子 Clock 物件 |
使用 ApplyAnimationClock 方法,可以將您建立的任何 AnimationClock 物件套用至相容的相依性屬性。
在會耗損效能的情況中,如顯示大量類似物件的動畫,管理您自己的 Clock 之使用可以提升效能。
時鐘和時間管理員
當您在 WPF 中將物件顯示為動畫,其實會替時刻表建立時間管理員,以便管理 Clock 物件。時間管理員是 Clock 物件的樹狀目錄的根,控制了這個樹狀目錄中的時間流程。每個 WPF 應用程式都會自動建立時間管理員,而且應用程式開發人員看不見時間管理員。時間管理員每秒「跳動」許多次;每秒跳動的實際次數依可用的系統資源而異。時間管理員每跳動一次,就會計算計時樹狀目錄中所有 Active Clock 物件的狀態。
下圖顯示時間管理員、AnimationClock 和用來建立動畫的相依性屬性之間的關係。
建立屬性的動畫
時間管理員每跳動一次,就會更新應用程式中每個 Active Clock 的時間。如果 Clock 是 AnimationClock,則會使用建立它的 AnimationTimeline 的 GetCurrentValue 方法,來計算目前的輸出值。AnimationClock 會提供 AnimationTimeline 目前本機時間、輸入值 (通常是屬性的基底實值) 和預設目的值。當您使用 GetValue 方法或它的 CLR 存取子擷取動畫屬性值時,會得到它的 AnimationClock 的輸出。
時鐘群組
前一節中說明了不同時刻表類型如何有不同類型的 Clock 物件。下圖顯示時間管理員、ClockGroup、AnimationClock 和以動畫顯示之相依性屬性之間的關係。如果時刻表是由其他時刻表組成的群組 (例如由動畫和其他時刻表組成的 Storyboard 類別),則會建立 ClockGroup。
ClockGroup
撰寫
您可以使數個時鐘和單一屬性產生關聯,在這種情況下每一個時鐘都使用前一個時鐘的輸出值做為它的基底實值。下圖顯示套用到相同屬性的三個 AnimationClock 物件。時鐘1 使用動畫屬性的基底實值做為輸入,並用它來產生輸出。時鐘2 拿時鐘1 的輸出做為輸入,並用它來產生輸出。時鐘3 拿時鐘2 的輸出做為輸入,並用它來產生輸出。當有數個時鐘同時影響同一個屬性,即稱這些時鐘形成撰寫鏈結。
撰寫鏈結
請注意,雖然 AnimationClock 物件的輸入和輸出之間建立了撰寫鏈結關係,但是它們的計時行為不會受影響;Clock 物件 (包括 AnimationClock 物件) 與它們的父 Clock 物件有階層上的相依性。
若要套用數個時鐘至同一個屬性,請在套用 Storyboard、動畫或 AnimationClock 時使用 Compose HandoffBehavior。
跳動和事件的合併
除了計算輸出值,時間管理員也會在它每次跳動時執行其他工作:判斷每個時鐘的狀態,並在適當時引發事件。
雖然跳動發生頻繁,但每次跳動之間仍可能發生許多事情。例如,Clock 可能已停止、又啟動,然後又再度停止,在這個情況下它的 CurrentState 值已經變更三次。理論上,一次跳動可以引發 CurrentStateInvalidated 事件許多次;但是時間引擎會合併事件,使得每一次跳動最多只會引發 CurrentStateInvalidated 事件一次。所有的計時事件皆是如此:每種類型的事件最多只會發生於特定 Clock 物件一次。
當 Clock 在跳動之間切換狀態然後又回到它的原始狀態 (例如從 Active 變為 Stopped 然後又變回 Active),相關聯的事件仍會發生。
如需計時事件的詳細資訊,請參閱計時事件概觀。
屬性的目前值和基底實值
可用來建立動畫的屬性會有兩個值:基底實值和目前值。當您使用屬性的 CLR 存取子或 SetValue 方法設定屬性值時,是在設定它的基底實值。當屬性沒有用來建立動畫時,它的基底實值和目前值相同。
當您以屬性建立動畫時,AnimationClock 設定的是動畫的「目前」值。當 AnimationClock 為 Active 或 Filling 時,透過屬性的 CLR 存取子或 GetValue 方法擷取屬性的值,將會傳回 AnimationClock 的輸出。您可以使用 GetAnimationBaseValue 方法擷取屬性的基底實值。