65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中的高级动画

starIconstarIconstarIconstarIconstarIcon

5.00/5 (17投票s)

2012年4月30日

CPOL

3分钟阅读

viewsIcon

89951

downloadIcon

4000

本文介绍了 WPF 中的高级动画。

引言

本文是我的上一篇文章《在 WPF 中使用 Storyboard 的动画》的延续。 在那篇文章中,我介绍了 Double Animation 和 Color Animation。 在本文中,我将介绍 KeyFrame Animation、Path Animation 和 Matrix Animation。 Double Animation 和 Color Animation 是简单的动画,它们具有起始点和结束点。 因此,很难将它们用于更复杂的动画。 我们可以使用 KeyFrame Animation、Path Animation 和 Matrix Animation 更好地控制复杂的动画。

  1. 关键帧动画基于关键帧,关键帧定义了动画的重要点。 中间帧稍后绘制。 WPF 会自动生成中间帧。
  2. 路径动画允许您使用 PathGeometry 定义对象遵循的路径。 这比关键帧动画更容易。
  3. 矩阵动画是一种特殊类型的路径动画。 矩阵动画可用于控制对象的位置和方向。

背景

线性关键帧动画

以下代码使用线性关键帧动画来设置椭圆的动画

<Canvas>
    <Ellipse Fill="Red" Width="70" Height="70">
        <Ellipse.Triggers>
            <EventTrigger RoutedEvent="Ellipse.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation From="0" To="400" Duration="0:0:5" 
                                 Storyboard.TargetProperty="(Canvas.Left)" 
                                 RepeatBehavior="Forever" AutoReverse="True"/>
                            <DoubleAnimationUsingKeyFrames Duration="0:0:2" 
                                   Storyboard.TargetProperty="(Canvas.Top)" 
                                   RepeatBehavior="Forever">
                                <DoubleAnimationUsingKeyFrames.KeyFrames>
                                    <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                    <LinearDoubleKeyFrame Value="50" KeyTime="0:0:0.5"/>
                                    <LinearDoubleKeyFrame Value="200" KeyTime="0:0:1"/>
                                    <LinearDoubleKeyFrame Value="50" KeyTime="0:0:1.5"/>
                                    <LinearDoubleKeyFrame Value="0" KeyTime="0:0:2"/>
                                </DoubleAnimationUsingKeyFrames.KeyFrames>
                            </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Ellipse.Triggers>
    </Ellipse>
</Canvas>

在上面的代码中,使用了一个简单的 DoubleAnimation 来控制椭圆的水平移动,从 0 到 400,持续时间为 5 秒。 DoubleAnimationUsingKeyFrames 元素控制椭圆的垂直移动。 它指定了 5 个关键帧,间隔为 0.5 秒。 LinearDoubleKeyFrame 元素用于指定关键帧。 LinearDoubleKeyFrame 不会产生平滑的动画,因为两个帧之间的值变化是恒定的。

以下是上述代码的输出:

样条关键帧动画

要创建平滑的动画,我们可以使用 SplineDoubleKeyFrameSplineDoubleKeyFrame 使用数学函数来计算对象应该如何加速或减速。 可以使用 KeySpline 属性来指定此值。

下图说明了这一点

以下代码使用 SplineDoubleKeyFrame 生成平滑的动画

<Canvas>
    <Ellipse Fill="Red" Width="70" Height="70">
        <Ellipse.Triggers>
            <EventTrigger RoutedEvent="Ellipse.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation From="0" To="400" Duration="0:0:10" 
                             Storyboard.TargetProperty="(Canvas.Left)" 
                             RepeatBehavior="Forever" AutoReverse="True"/>
                        <DoubleAnimationUsingKeyFrames Duration="0:0:2" 
                               Storyboard.TargetProperty="(Canvas.Top)" 
                               RepeatBehavior="Forever">
                            <DoubleAnimationUsingKeyFrames.KeyFrames>
                                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0"/>
                                        <SplineDoubleKeyFrame Value="50" 
                                           KeyTime="0:0:0.5" KeySpline="0.4,0 0.7,0.7"/>
                                        <SplineDoubleKeyFrame Value="200" 
                                           KeyTime="0:0:1" KeySpline="0.2,0.2 0.7,0.4"/>
                                        <SplineDoubleKeyFrame Value="50" 
                                           KeyTime="0:0:1.5" KeySpline="0,0.3 0.75,0.75"/>
                                        <SplineDoubleKeyFrame Value="0" 
                                           KeyTime="0:0:2.0" KeySpline="0.25,0.25 0.6,1"/>
                                    </DoubleAnimationUsingKeyFrames.KeyFrames>
                            </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Ellipse.Triggers>
    </Ellipse>
</Canvas>

上面的代码通过使动画在缓慢开始后逐渐加速来产生更逼真的动画。

以下是上述代码的输出

路径动画

路径动画可用于通过更改对象的位置来在画布上移动对象。 这可以通过设置 Canvas.LeftCanvas.Top 属性来完成。 由于这些属性的类型为 double,因此我们可以使用 DoubleAnimationUsingPath 来设置对象的动画。

以下是使用路径动画在椭圆路径上移动椭圆的代码。

<Canvas>
    <Canvas.Resources>
        <PathGeometry x:Key="MyGeometry" 
          Figures="M 0,30 A 30,30 180 0 1 60,30 30,30 180 0 1 0,30"/>
    </Canvas.Resources>
    <Ellipse Width="50" Height="50" Fill="Green">
        <Ellipse.Triggers>
            <EventTrigger RoutedEvent="Window.Loaded">
                <BeginStoryboard>
                    <Storyboard RepeatBehavior="Forever">
                        <DoubleAnimationUsingPath Source="X" 
                          Storyboard.TargetProperty="(Canvas.Left)" 
                          PathGeometry="{StaticResource MyGeometry}"/>
                        <DoubleAnimationUsingPath Source="Y" 
                          Storyboard.TargetProperty="(Canvas.Top)" 
                          PathGeometry="{StaticResource MyGeometry}"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Ellipse.Triggers>
    </Ellipse>
</Canvas>

上面的代码创建了一个 PathGeometry 对象作为画布资源。 然后,它使用 DoubleAnimationUsingPathPathGeometry 属性来更改椭圆在路径上的位置。 要了解 PathGeometry 的语法,请参考以下链接:http://msdn.microsoft.com/en-us/library/ms752293.aspx

以下是上述代码的输出:

矩阵动画

矩阵动画可用于控制对象的位置和方向。 我们可以使用 DoesRotateWithTangent 属性来控制对象在路径上的旋转。 我使用以下代码在路径上移动一个箭头。

<Canvas>
    <Path Name="MyPath" StrokeThickness="7">
        <Path.Stroke>
            <SolidColorBrush x:Name="MyBrush" Color="Red"/>
        </Path.Stroke>
        <Path.Data>
            <PathGeometry Figures="M 0,0 H45 M 35,-10 L 45,0,35,10"/>
        </Path.Data>
        <Path.RenderTransform>
            <MatrixTransform x:Name="MyMatrixTransform">
                <MatrixTransform.Matrix>
                    <Matrix/>
                </MatrixTransform.Matrix>
            </MatrixTransform>
        </Path.RenderTransform>
        <Path.Triggers>
            <EventTrigger RoutedEvent="Window.Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <Storyboard AutoReverse="True" RepeatBehavior="Forever">
                            <ColorAnimation Storyboard.TargetName="MyBrush" 
                               Storyboard.TargetProperty="Color" From="Red" To="Green" 
                               BeginTime="0:0:0" Duration="0:0:1"/>
                            <ColorAnimation Storyboard.TargetName="MyBrush" 
                               Storyboard.TargetProperty="Color" From="Green" 
                               To="Blue" BeginTime="0:0:1" Duration="0:0:1"/>
                            <ColorAnimation Storyboard.TargetName="MyBrush" 
                               Storyboard.TargetProperty="Color" From="Blue" 
                               To="Cyan" BeginTime="0:0:2" Duration="0:0:1"/>
                            <ColorAnimation Storyboard.TargetName="MyBrush" 
                               Storyboard.TargetProperty="Color" From="Cyan" 
                               To="Magenta" BeginTime="0:0:3" Duration="0:0:1"/>
                            <ColorAnimation Storyboard.TargetName="MyBrush" 
                               Storyboard.TargetProperty="Color" From="Magenta" 
                               To="Red" BeginTime="0:0:4" Duration="0:0:1"/>
                        </Storyboard>
                        <MatrixAnimationUsingPath Storyboard.TargetName="MyMatrixTransform" 
                                  Storyboard.TargetProperty="Matrix" DoesRotateWithTangent="True" 
                                  Duration="0:0:5" RepeatBehavior="Forever">
                            <MatrixAnimationUsingPath.PathGeometry>
                                <PathGeometry Figures="M 100,200 C 100,25 400,350 400,175"/>
                            </MatrixAnimationUsingPath.PathGeometry>
                        </MatrixAnimationUsingPath>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Path.Triggers>
    </Path>
</Canvas>

上面的代码使用 MatrixAnimationUsingPath 沿着使用 PathGeometry 定义的路径移动一个箭头,并使用 ColorAnimation 在箭头移动时更改其颜色。 我创建了一个箭头,如下所示 ,使用以下路径几何

<PathGeometry Figures="M 0,0 H45 M 35,-10 L 45,0,35,10"/>

以及如下所示的路径

使用以下路径几何

<PathGeometry Figures="M 100,200 C 100,25 400,350 400,175"/>

DoesRotateWithTangent 属性设置为 true 以使箭头沿着路径旋转。

以下是上述代码的输出

如果将 DoesRotateWithTangent 属性设置为 false,则以下是上述代码的输出

使用代码

我创建了一个应用程序,该应用程序使用标签界面演示了所有上述动画。

关注点

我使用 Visual C# 2010 Express Edition 完成了所有编码。 我希望读者发现本文有助于理解 WPF 中动画的各个方面。

© . All rights reserved.