Welcome

首页 / 软件开发 / .NET编程技术 / 扩展WPF动画类

扩展WPF动画类2010-04-19周银辉对 Microsoft® Windows® Presentation Foundation 中动画的支持大部分收集在 System.Windows.Media.Animation 命名空间中。这是一个大型命名空间,其中定义了 164 个类专用于设置 22 种特定数据类型的动画属性。这 22 种数据类型包括基本数据类型(如 byte、int 和 double),也包括更特殊的类型(如 Matrix、Point3D 和 Quaternion)。

Windows Presentation Foundation 中的动画资源毫无疑问是引人入胜的作品,但恐怕只有非编程人员才会认为这 22 种数据类型就足够满足各种应用程序。我个人经常开发希望对整个对象集合实现动画效果的应用程序,尤其是坐标点的集合。现有的 API 为我们提供了类(如 PointAnimation 和 Point3DAnimation)来制作单独的 2D 或 3D 坐标的动画,但我希望 PointCollectionAnimation 和 Point3DCollectionAnimation 类通过在两个集合的相应成员之间插入来制作整个坐标点集合的动画。

通常,我们可能会责怪 Microsoft .NET Framework(尤其是 Windows Presentation Foundation)使得定义对象集合如此轻松,使用起来如此便利,就像使用对象本身一样。Windows Presentation Foundation 已定义了 PointCollection 和 Point3DCollection 类,而且在 XAML 中,这些集合的使用方法非常简单。在 XAML 中,分配 Point 类型的属性和分配 PointCollection 类型的属性之间的差别就像键入“100 50”和“100 50, 40 25, 35 80, 50 100”之间的差别一样。因此,我想为什么使这些类型的属性具有动画效果不能像这般简单呢?

假定 PointCollectionAnimation 类将会使 PointCollection 类型的属性具有动画效果。Windows Presentation Foundation 中内置的五个类具有该类型的属性:Polyline、Polygon(两者均源于 Shape)、PolyLineSegment、PolyBezierSegment 和 PolyQuadraticBezierSegment(源于 PathSegment)五个类的属性均指定为 Points。通过使这些 Points 属性具有动画效果,您可以将图形数字从一个形状更改到另一个具有单个动画的形状。

据我所知,Point3DCollection 仅能在一个类中显示,即位于 Windows Presentation Foundation 3D 图形系统中心的 MeshGeometry3D 类。通过制作 Point3DCollection would 动画,可以非常轻松地实现 3D 对象变形(通常被认为是相当高级的 3D 编程任务)。

正是在计算机屏幕上切换、变形和改变 2D 和 3D 图的形状的想象促使我在扩展 Windows Presentation Foundation 动画类的道路上不断前进。

插入值

在 Windows Presentation Foundation 中,动画基本上为插值,通常情况下为线性插值。使新动画类编码复杂化的因素并非插值操作本身,而是确定要在其间插入的确切值。

我们来看一个涉及到 Point 值动画的简单示例。您可以在 XAML 中画一个实心圆形,如下所示:

<Path Fill=”Blue”>
<Path.Data>
<EllipseGeometry x:Name=”ellipse”
RadiusX=”10” RadiusY=”10” />
</Path.Data>
</Path>

在此标记中未指定 EllipseGeometry 的 Center 属性,这是 Point 类型的属性。您可以通过 PointAnimation 元素使 Center 属性具有动画效果,如下所示:

<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
From=”10 10” To=”100 100”
Duration=”0:0:3” />

Center 属性在三秒钟内从点(10,10)移动到点(100,100),这表示 PointAnimation 类基于这段时间在两个值之间执行线性插入。

您还可以在 EllipseGeometry 标记中指定 Center 属性,如下所示:

<EllipseGeometry x:Name=”ellipse” Center=”50 50” ...

此值称为基值,因为动画可以基于此值构建。您可以通过省略 PointAnimation 标记中的 From 或 To 属性来充分利用此基值,如以下标记中所示:

<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
To=”100 100”
Duration=”0:0:3” />

现在该动画从 EllipseGeometry 标记中指定的中心点(50,50)开始,到点(100,100)结束。允许使用以下语法:

<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
From=”100 100”
Duration=”0:0:3” />

现在该动画从点(100,100)开始,到点(50,50)结束。如果 From 或 To 属性缺失,而且 EllipseGeometry 标记未指定 Center 属性,则该动画将采用 Center 属性的默认值,即(0,0)。

好像越来越乱了。To 属性的一个备选项是 By 属性,即起始点的增量。

<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
From=”100 100” By=”125 125”
Duration=”0:0:3” />

现在此动画在(100,100)到(225,225)之间移动。但无需显示 From 属性。

<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
By=”125 125”
Duration=”0:0:3” />

现在该动画从 EllipseGeometry 标记中指定的点(50,50)开始,到点(175,175)结束。

动画的基值通常是最初为需要动画效果的属性定义的值,但不必一定是该值。请考虑以下两个顺序 PointAnimation 对象:

<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
To=”100 100” Duration=”0:0:3” />
<PointAnimation Storyboard.TargetName=”ellipse”
Storyboard.TargetProperty=”Center”
BeginTime=”0:0:5” Duration=”0:0:3” />

在前三秒内,初始动画将 Center 属性从其基值(50,50)更改到 To 值(100,100),在此处,该值再停留两秒钟,直到第二个动画到达。此动画完全没有 From、To 或 By 属性!该动画开始于基值(100,100),结束于 EllipseGeometry 标记中指定的值(50,50)。

您可以看到,一个类(如 PointAnimation)具有两个默认值用于动画开始和结束;如果没有为特定动画对象定义 From、To 和 By 属性,则动画将使用这些默认值。这些类还定义了两个 Boolean 属性,分别为 IsAdditive(使动画值添加到基值)和 IsCumulative(如果动画不断重复,则累积动画值)。这些属性均无法使动画在逻辑上更加简单。