本主题介绍如何以及何时通过创建自定义关键帧、动画类或使用每帧回调绕过 WPF 动画系统来扩展 WPF 动画系统。
先决条件
若要了解本主题,应熟悉 WPF 提供的不同类型的动画。 有关详细信息,请参阅 From/To/By 动画概述、 Key-Frame 动画概述和 路径动画概述。
由于动画类继承自 Freezable 该类,因此应熟悉 Freezable 对象以及如何从 Freezable中继承。 有关详细信息,请参阅 冻结对象概述。
扩展动画系统
可通过多种方式扩展 WPF 动画系统,具体取决于要使用的内置功能级别。 WPF 动画引擎中有三个主要扩展点:
通过继承自 *Type<*>KeyFrame 类之一(例如DoubleKeyFrame)创建自定义关键帧对象。 此方法使用 WPF 动画引擎的大部分内置功能。
通过继承自 AnimationTimeline 或 *
使用每帧回调函数生成逐帧动画。 此方法完全绕过动画和计时系统。
下表介绍了扩展动画系统的一些方案。
需要执行以下操作时:
使用此方法
自定义在具有相应 *
创建自定义关键帧。 有关详细信息,请参阅“ 创建自定义关键帧 ”部分。
自定义的不仅仅是具有相应 *
创建自定义动画类,该类继承自 *
对没有相应 WPF 动画的类型进行动画处理
使用ObjectAnimationUsingKeyFrames或创建一个继承自AnimationTimeline的类。 有关详细信息,请参阅“ 创建自定义动画类 ”部分。
为多个对象制作动画,这些动画的值是每帧计算的,并基于最后一组对象交互。
使用每帧回调。 有关详细信息,请参阅“创建使用 Per-Frame 回调”部分。
创建自定义关键帧
创建自定义关键帧类是扩展动画系统的最简单方法。 如果要为关键帧动画使用不同的内插方法,请使用此方法。 如 Key-Frame 动画概述中所述,关键帧动画使用关键帧对象生成其输出值。 每个关键帧对象执行三个函数:
使用其 Value 属性指定目标值。
指定应使用其 KeyTime 属性访问该值的时间。
通过实现 InterpolateValueCore 方法,在上一个关键帧的值与其自己的值之间进行内插。
实现说明
派生自 *
由于 *
创建自定义 *
创建自定义动画类
创建自己的动画类型可让你更好地控制动画中的对象的方式。 创建自己的动画类型有两种建议方法:可以从 AnimationTimeline 类派生或从 *
派生自
从 *
实现说明
派生自 *
由于 *
有关详细信息,请参阅要进行动画处理的类型的 *
替代方法
如果你只是想更改动画值的插值方式,可以考虑继承自 *
派生自 AnimationTimeline
当您想为尚未具有匹配 WPF 动画的类型创建动画,或者想创建非强类型化的动画时,请从 AnimationTimeline 类派生。
实现说明
派生自 AnimationTimeline 类并重写以下成员:
CreateInstanceCore – 如果新类是具体类,则必须重写 CreateInstanceCore 才能返回类的新实例。
GetCurrentValue – 重写此方法以返回动画的当前值。 它采用三个参数:默认源值、默认目标值和一个 AnimationClock。 使用此方法 AnimationClock 获取动画的当前时间或进度。 可以选择是否使用默认源和目标值。
IsDestinationDefault – 重写此属性以指示您的动画是否使用由GetCurrentValue方法指定的默认目标值。
TargetPropertyType – 重写此属性以指示 Type 动画生成的输出。
如果类不使用依赖属性来存储其数据,或者需要在创建后进行额外的初始化,则可能需要重写其他方法;有关详细信息,请参阅 冻结对象概述 。
推荐的范式(用于 WPF 动画)是使用两层继承级别:
创建一个抽象的*
创建另一个继承自新 *
替代方法
如果想对某个类型进行动画处理,但该类型没有对应的 From/To/By 动画或关键帧动画,请考虑使用 ObjectAnimationUsingKeyFrames。 由于它是弱类型,因此 ObjectAnimationUsingKeyFrames 可以对任何类型的值实现动画效果。 此方法的缺点是 ObjectAnimationUsingKeyFrames 仅支持离散插值。
使用 Per-Frame 回调
如果需要完全绕过 WPF 动画系统,请使用此方法。 此方法的一种方案是物理动画,其中在每个动画步骤中,需要根据最后一组对象交互重新计算动画对象的新方向或位置。
实现说明
与本概述中所述的其他方法不同,若要使用每帧回调,无需创建自定义动画或关键帧类。
您应该注册包含要进行动画处理对象的父对象的Rendering事件。 每个帧调用一次此事件处理程序方法。 每次 WPF 将可视化树中持久呈现数据封送到合成树时,都会调用事件处理程序方法。
在事件处理程序中,执行动画效果所需的任何计算,并设置要使用这些值进行动画处理的对象的属性。
若要获取当前帧的呈现时间,可以将与此事件关联的EventArgs强制转换为RenderingEventArgs,从而提供一个RenderingTime属性,您可以通过该属性获取当前帧的渲染时间。
有关详细信息,请参阅 Rendering 页面。
另请参阅
AnimationTimeline
IKeyFrame
属性动画技术概述
可冻结对象概述
Key-Frame 动画概述
路径动画概述
动画概述
动画和计时系统概述
自定义动画示例