自訂動畫概觀
本主題說明如何及何時建立自訂主要畫面格、動畫類別來擴充 WPF 動畫系統,或使用個別畫面格回呼來略過它。
必要條件
若要了解本主題,您應該熟悉 WPF 提供的不同動畫類型。 如需詳細資訊,請參閱<From/To/By 動畫概觀>、主要畫面格動畫概觀以及路徑動畫概觀。
因為動畫類別繼承自 Freezable 類別,所以您應該熟悉 Freezable 物件,以及如何繼承自 Freezable。 如需詳細資訊,請參閱 Freezable 物件概觀。
擴充動畫系統
有數種方式可以擴充 WPF 動畫系統,視您想要使用的內建功能層級而定。 WPF 動畫引擎中有三個主要擴充點:
從 *<Type>*KeyFrame 類別之一繼承來建立自訂主要畫面格物件,例如 DoubleKeyFrame。 這個方法可使用大部分的 WPF 動畫引擎內建功能。
從 AnimationTimeline 或 *<Type>*AnimationBase 類別之一繼承來建立您自己的動畫類別。
您可以針對每一畫面格使用每一畫面的回呼來產生動畫。 這個方法完全略過動畫與計時系統。
下表說明一些擴充動畫系統的案例。
當您要... | 使用這個方法 |
---|---|
在有對應 *<Type>*AnimationUsingKeyFrames 的類型值之間自訂內插補點 | 建立自訂主要畫面格。 如需詳細資訊,請參閱建立自訂主要畫面格一節。 |
不只是在有對應 *<Type>*Animation 的類型值之間自訂內插補點。 | 建立自訂動畫類別,其繼承自和您想要以動畫顯示之類型對應的 *<Type>*AnimationBase 類別。 如需詳細資訊,請參閱建立自訂動畫類別一節。 |
以動畫顯示沒有對應 WPF 動畫的類型 | 使用 ObjectAnimationUsingKeyFrames 或建立繼承自 AnimationTimeline 的類別。 如需詳細資訊,請參閱建立自訂動畫類別一節。 |
利用每個畫面格都會計算的值,並根據最後一組物件互動的值,以動畫顯示多個物件 | 使用每一畫面的回呼。 如需詳細資訊,請參閱使用每一畫面的回呼一節。 |
建立自訂主要畫面格
建立自訂主要畫面格類別是擴充動畫系統最簡單的方式。 當您想要不同的主要畫面格動畫內插補點方法時,請使用這個方法。 如主要畫面格動畫概觀中所述,主要畫面格動畫使用主要畫面格物件來產生其輸出值。 每個主要畫面格物件都會執行三個函式︰
實作指示
衍生自 *<Type>*KeyFrame 抽象類別並實作 InterpolateValueCore 方法。 InterpolateValueCore 方法會傳回主要畫面格目前的值。 它接受兩個參數︰前一個主要畫面格的值和範圍從 0 到 1 的進度值。 進度為 0 表示主要畫面格正好開始,而值為 1 表示主要畫面格正好結束,並應該傳回其 Value 屬性指定的值。
因為 *<Type>*KeyFrame 類別繼承自 Freezable 類別,所以您也必須覆寫 CreateInstanceCore 核心以傳回類別的新執行個體。 如果類別不使用相依性屬性來儲存其資料或需要在建立之後額外進行初始化,您可能需要覆寫其他方法。如需詳細資訊,請參閱 Freezable 物件概觀。
建立自訂 *<Type>*KeyFrame 動畫之後,可將其與該類型的 *<Type>*AnimationUsingKeyFrames 搭配使用。
建立自訂動畫類別
建立您自己的動畫類型可讓您更充分掌控物件的動畫效果。 有兩種建議做法可以建立您自己的動畫類型:您可以衍生自 AnimationTimeline 類別或 *<Type>*AnimationBase 類別。 不建議衍生自*<Type>*Animation 或 *<Type>*AnimationUsingKeyFrames 類別。
衍生自 <Type>AnimationBase
衍生自 *<Type>*AnimationBase 類別是建立新動畫類型最簡單的方式。 當您想要對已有對應 *<Type>*AnimationBase 類別的類型建立新動畫時,請使用此方法。
實作指示
衍生自 *<Type>*Animation 類別並實作 GetCurrentValueCore 方法。 GetCurrentValueCore 方法會傳回動畫目前的值。 它接受三個參數:建議的起始值、建議的結束值,以及您用來判斷動畫進度的 AnimationClock。
因為 *<Type>*AnimationBase 類別繼承自 Freezable 類別,所以您也必須覆寫 CreateInstanceCore 核心以傳回類別的新執行個體。 如果類別不使用相依性屬性來儲存其資料或需要在建立之後額外進行初始化,您可能需要覆寫其他方法。如需詳細資訊,請參閱 Freezable 物件概觀。
如需詳細資訊,請參閱您想要以動畫顯示之類型的 *<Type>*AnimationBase 類別適用的 GetCurrentValueCore 方法文件。 如需範例,請參閱自訂動畫範例
替代方法
如果您只想要變更插入動畫值的方式,請考慮衍生自 *<Type>*KeyFrame 類別之一。 您建立的主要畫面格可以與 WPF 提供的對應 *<Type>*AnimationUsingKeyFrames 搭配使用。
衍生自 AnimationTimeline
當您想要對目前沒有對應 WPF 動畫的類型建立動畫,或想要建立非強型別的動畫時,可衍生自 AnimationTimeline 類別。
實作指示
衍生自 AnimationTimeline 類別並覆寫下列成員:
CreateInstanceCore - 如果您的新類別固定不變,您必須覆寫 CreateInstanceCore 以傳回類別的新執行個體。
GetCurrentValue - 覆寫此方法以傳回動畫目前的值。 它接受三個參數︰預設原始值、預設目的值以及 AnimationClock。 使用 AnimationClock 以取得該動畫目前的時間或進度。 您可以選擇是否要使用預設的來源和目的值。
IsDestinationDefault - 覆寫此屬性以指出您的動畫是否要使用 GetCurrentValue 方法指定的預設目的值。
TargetPropertyType - 覆寫此屬性以指定您的動畫所產生輸出的 Type。
如果類別不使用相依性屬性來儲存其資料或需要在建立之後額外進行初始化,您可能需要覆寫其他方法。如需詳細資訊,請參閱 Freezable 物件概觀。
建議的範例 (由 WPF 動畫使用) 是使用兩個繼承層級:
建立衍生自 AnimationTimeline 的抽象 *<Type>*AnimationBase 類別。 此類別應該覆寫 TargetPropertyType 方法。 它也應該引進新的抽象方法 GetCurrentValueCore,並覆寫 GetCurrentValue 以驗證預設原始值和預設目的值參數的類型,然後呼叫 GetCurrentValueCore。
建立繼承自新 *<Type>*AnimationBase 類別的另一個類別,並覆寫 CreateInstanceCore 方法、您引進的 GetCurrentValueCore 方法以及 IsDestinationDefault 屬性。
替代方法
如果您想要以動畫顯示沒有對應 From/To/By 動畫或主要畫面格動畫的類型,請考慮使用 ObjectAnimationUsingKeyFrames。 因為它是弱式型別,所以 ObjectAnimationUsingKeyFrames 能以動畫顯示任何類型的值。 這個方法的缺點在於 ObjectAnimationUsingKeyFrames 只支援離散插補。
使用每一畫面的回呼
當您需要完全略過 WPF 動畫系統時,請使用此方法。 此方法的一個案例為物理動畫,其中的每個動畫步驟都需要根據最後一組物件互動來重新計算動畫物件的新方向或位置。
實作指示
和本概觀中所述的其他方法不同,若要使用每一畫面的回呼,您不需要建立自訂動畫或主要畫面格類別。
相反地,您必須註冊物件 (其中包含您想要以動畫顯示的物件) 的 Rendering 事件。 系統會針對每個畫面呼叫一次此事件處理常式方法。 WPF 每次封送處理視覺化樹狀結構中已保存的轉譯資料,跨越到組合樹狀結構時,就會呼叫您的事件處理常式方法。
在事件處理常式中,執行動畫效果所需的任何計算,並使用這些值設定您想要建立動畫的物件屬性。
若要取得目前畫面格的呈現時間,與此事件相關聯的 EventArgs 可以轉換成 RenderingEventArgs,這會為您提供可用來取得目前畫面格轉譯時間的 RenderingTime 屬性。
如需詳細資訊,請參閱 Rendering 頁面。