首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

擴展 WPF 動畫類別:實現 PointCollection 與 Point3DCollection 動畫

     編輯:關於.NET

前言:為何需要擴展動畫類別?

Windows Presentation Foundation (WPF) 的動畫系統極為強大,核心類別集中在 System.Windows.Media.Animation 命名空間,內建 164 個類別支援 22 種資料類型的屬性動畫,涵蓋基本型別(byte、int、double)與進階型別(Matrix、Point3D、Quaternion)。然而,實際開發中常需對「集合」進行動畫,例如座標點集合。雖然 API 提供 PointAnimation 與 Point3DAnimation 處理單一點,但缺乏 PointCollectionAnimation 與 Point3DCollectionAnimation 以在兩個集合對應成員間插值,實現整組點的變形動畫。

WPF 定義了 PointCollection 與 Point3DCollection,XAML 中使用極為簡單(如 Points="100 50, 40 25, 35 80, 50 100")。既然集合賦值如此直觀,為何動畫不能同樣簡單?本文將示範如何擴展動畫類別,實現集合層級的動畫,並應用於 2D 圖形變形、文字變形與 3D 模型扭曲等進階場景。

動畫的核心:插值與基值

WPF 動畫本質是插值(通常為線性插值)。複雜度不在插值運算,而在於確定「從哪裡插到哪裡」。以 PointAnimation 為例,可指定 From、To、By,亦可省略從基值(Base Value)開始或結束。基值通常是屬性初始值,但若有多個動畫先後作用同一屬性,基值會動態改變。此外 IsAdditive、IsCumulative 等屬性更增加邏輯複雜度。自訂動畫類別必須正確處理這些情況。

類別架構:遵循 WPF 模式

WPF 動畫類別遵循固定階層:<Type>AnimationBase(抽象)→ <Type>Animation(線性插值)→ <Type>AnimationUsingKeyFrames(關鍵幀)。繼承自 AnimationTimeline → Animatable → Timeline → Freezable。自訂類別需:

  1. 建立抽象 PointCollectionAnimationBase 繼承 AnimationTimeline,覆寫 TargetPropertyType 回傳 typeof(PointCollection)。
  2. 覆寫 GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock),根據 animationClock.CurrentProgress (0~1) 計算插值。
  3. 定義強型別 GetCurrentValue(PointCollection, PointCollection, AnimationClock) 呼叫受保護抽象方法 GetCurrentValueCore,由具體子類別實作。

動畫類別階層 動畫類別階層大圖

Freezable 機制與記憶體管理

所有動畫類別最終繼承 Freezable,非抽象類別必須覆寫 CreateInstanceCore。為避免動畫期間頻繁配置記憶體,PointCollectionAnimation 內部預先建立兩個 PointCollection 欄位(ptsDst1、ptsDst2)交替使用,並以 ptsTo 儲存目標點集合。關鍵程式碼見下圖:

GetCurrentValueCore 實作

應用範例:2D 圖形與文字變形

正方形變圓形

利用 PointCollectionAnimation 驅動 PolyBezierSegment.Points,單一動畫即可完成書本中需 13 個 PointAnimation 才能達成的「正方形變圓形」效果。XAML 如下:

<pae:PointCollectionAnimation
  Storyboard.TargetName="seg"
  Storyboard.TargetProperty="Points"
  From="55 100, 100 55, ..."
  To="62.5 62.5, 62.5 62.5, ..."
  Duration="0:0:3"
  RepeatBehavior="Forever" AutoReverse="True" />

Checkbox 文字變形

定義兩個 PointCollection 資源分別描述「否」與「是」的筆畫路徑,透過 PointCollectionAnimation 在兩者間插值,實現文字筆畫的平滑變形。點集合取自 Windows 早期矢量字體,經手動調整點數一致。

變形文字複選框a 變形文字複選框b 變形文字複選框c 變形文字複選框d 變形文字複選框e 變形文字複選框f

關鍵幀動畫:PointCollectionAnimationUsingKeyFrames

關鍵幀動畫支援離散、線性、樣條三種插值。實作步驟:

  1. 抽象 PointCollectionKeyFrame 實作 IKeyFrame,定義 KeyTime、Value 與 InterpolateValueCore。
  2. 三具體類別:DiscretePointCollectionKeyFrame、LinearPointCollectionKeyFrame、SplinePointCollectionKeyFrame(含 KeySpline 屬性)。
  3. PointCollectionKeyFrameCollection 繼承 FreezableCollection<T>。
  4. PointCollectionAnimationUsingKeyFrames 繼承 PointCollectionAnimationBase 實作 IKeyFrameAnimation,覆寫 GetCurrentValueCore 判斷當前活動關鍵幀。

新增 AccumulationPoint 屬性支援累積位移,示範「火柴人走路」動畫。

火柴人走路

3D 點集合動畫:自訂變形器模式

針對 MeshGeometry3D.Positions (Point3DCollection) 採不同策略:定義 IDeformer 介面,單一方法 Deform(Point3DCollection points, double progress)。Point3DCollectionAnimationUsingDeformer 僅持有 Deformer 屬性,將插值邏輯委派給實作類別。範例 Twister 實現扭曲變形:繞軸旋轉,角度隨距中心距離遞增。應用於經典 Utah Teapot 模型。

扭曲的茶壺

XAML 引用方式:

<pae:Point3DCollectionAnimationUsingDeformer
  Duration="0:0:5" AutoReverse="true" RepeatBehavior="Forever">
  <pae:Point3DCollectionAnimationUsingDeformer.Deformer>
    <pae:Twister Axis="1 0 0" />
  </pae:Point3DCollectionAnimationUsingDeformer.Deformer>
</pae:Point3DCollectionAnimationUsingDeformer>

結語

擴展 WPF 動畫類別雖需理解 Freezable、依賴屬性、插值邏輯等底層機制,但能解鎖集合層級動畫,實現 2D/3D 變形、文字筆畫動畫、非線性 3D 變形等高階效果。完整程式碼包含 Petzold.AnimationExtensions DLL 與四個示範專案,可作為進階 WPF 動畫開發的參考基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved