关键帧动画概述

本主题将向您介绍关键帧动画。 通过关键帧动画,您可以使用两个以上的目标值制作动画,并控制动画的内插方法。

本主题包括以下部分。

  • 先决条件

  • 使用关键帧动画

  • 相关主题

先决条件

若要理解本概述,您应熟悉 Windows Presentation Foundation (WPF) 动画和时间线。 有关动画的简介,请参见动画概述。它还有助于您熟悉 From/To/By 动画。 有关更多信息,请参见 From/To/By 动画概述

什么是关键帧动画?

与 From/To/By 动画类似,关键帧动画以动画形式显示了目标属性的值。 它通过其 Duration 创建其目标值之间的过渡。 但是,From/To/By 动画可以创建两个值之间的过渡,而单个关键帧动画则可以创建任意数量的目标值之间的过渡。 与 From/To/By 动画不同的是,关键帧动画没有设置其目标值所需的 From、To 或 By 属性。 关键帧动画的目标值是使用关键帧对象进行描述的,因此称作“关键帧动画”。 若要指定动画的目标值,您可以创建关键帧对象并将其添加到动画的 KeyFrames 集合内。 动画运行时,将在您指定的帧之间过渡。

某些关键帧方法除支持多个目标值外,还支持多个内插方法。 动画的内插方法定义了从某个值过渡到下一个值的方式。 有三种内插类型:离散、线性和样条。

若要对关键帧动画进行动画处理,需要完成下列步骤。

  • 声明动画并以针对 From/To/By 动画的方式指定其 Duration

  • 对于每一个目标值,创建相应类型的关键帧,设置其值和 KeyTime,并将其添加到动画的 KeyFrames 集合内。

  • 以针对 From/To/By 动画的方式将动画与属性相关联。 有关使用演示图板将动画应用到属性的更多信息,请参见演示图板概述

下面的示例使用 DoubleAnimationUsingKeyFramesRectangle 元素在四个不同的位置进行动画处理。

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
  WindowTitle="KeyFrame Animations">

  <Border Width="400" BorderBrush="Black">  

    <Rectangle Fill="Blue" 
      Width="50" Height="50"
      HorizontalAlignment="Left">
      <Rectangle.RenderTransform>
        <TranslateTransform 
          x:Name="MyAnimatedTranslateTransform" 
          X="0" Y="0" />
      </Rectangle.RenderTransform>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
          <BeginStoryboard>
            <Storyboard>

              <!-- Animate the TranslateTransform's X property
                   from 0 to 350, then 50,
                   then 200 over 10 seconds. -->

              <DoubleAnimationUsingKeyFrames
                Storyboard.TargetName="MyAnimatedTranslateTransform"
                Storyboard.TargetProperty="X"
                Duration="0:0:10">
                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
                <LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
                <LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
                <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />                          
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers> 
    </Rectangle>
  </Border> 
</Page>

您可以通过在标记和代码中使用 Storyboard,或者通过在代码中使用 BeginAnimation 方法以类似于针对 From/To/By 动画的方式将关键帧动画应用于属性。 还可以使用关键帧动画创建 AnimationClock,并将其应用于一个或多个属性。 有关应用动画的各种方法的更多信息,请参见属性动画技术概述

关键帧动画类型

由于动画生成属性值,因此对于不同的属性类型,会有不同的动画类型。 若要对采用 Double 的属性(例如元素的 Width 属性)进行动画处理,请使用生成 Double 值的动画。 若要对采用 Point 的属性进行动画处理,请使用生成 Point 值的动画,依此类推。

关键帧动画类属于 System.Windows.Media.Animation 命名空间,并遵守下列命名约定:

*<类型>*AnimationUsingKeyFrames

其中 <类型> 是该类进行动画处理的值的类型。

WPF 提供了以下关键帧动画类。

属性类型

对应的 From/To/By 动画类

支持的内插方法

Boolean

BooleanAnimationUsingKeyFrames

离散

Byte

ByteAnimationUsingKeyFrames

离散、线性、样条

Color

ColorAnimationUsingKeyFrames

离散、线性、样条

Decimal

DecimalAnimationUsingKeyFrames

离散、线性、样条

Double

DoubleAnimationUsingKeyFrames

离散、线性、样条

Int16

Int16AnimationUsingKeyFrames

离散、线性、样条

Int32

Int32AnimationUsingKeyFrames

离散、线性、样条

Int64

Int64AnimationUsingKeyFrames

离散、线性、样条

Matrix

MatrixAnimationUsingKeyFrames

离散

Object

ObjectAnimationUsingKeyFrames

离散

Point

PointAnimationUsingKeyFrames

离散、线性、样条

Quaternion

QuaternionAnimationUsingKeyFrames

离散、线性、样条

Rect

RectAnimationUsingKeyFrames

离散、线性、样条

Rotation3D

Rotation3DAnimationUsingKeyFrames

离散、线性、样条

Single

SingleAnimationUsingKeyFrames

离散、线性、样条

String

StringAnimationUsingKeyFrames

离散

Size

SizeAnimationUsingKeyFrames

离散、线性、样条

Thickness

ThicknessAnimationUsingKeyFrames

离散、线性、样条

Vector3D

Vector3DAnimationUsingKeyFrames

离散、线性、样条

Vector

VectorAnimationUsingKeyFrames

离散、线性、样条

目标值(关键帧)和关键时间

就像在对不同属性类型进行动画处理时有不同类型的关键帧动画一样,关键帧对象的类型也各不相同:对于每种进行动画处理的值和所支持的内插方法,都有一个对象类型。 关键帧类型遵守以下命名约定:

*<内插方法><类型>*KeyFrame

其中 <内插方法> 是关键帧使用的内插方法,<类型> 是类进行动画处理的值的类型。 支持所有三种内插方法的关键帧动画有三种关键帧类型可供您使用。 例如,您可以使用以下三种具有 DoubleAnimationUsingKeyFrames 的关键帧类型:DiscreteDoubleKeyFrameLinearDoubleKeyFrameSplineDoubleKeyFrame (后面部分将对内插方法进行详细说明)。

关键帧的主要用途是指定 KeyTimeValue。 每个关键帧类型都可提供这两种属性。

  • Value 属性指定该关键帧的目标值。

  • KeyTime 属性指定到达关键帧的 Value 的时间(在动画的 Duration 之内)。

关键帧动画开始后,会按照由关键帧 KeyTime 属性定义的顺序来循环访问其关键帧。

  • 如果时间 0 上没有关键帧,动画将在目标属性当前值和第一个关键帧的 Value 之间创建一个过渡;否则,动画的输出值将成为第一个关键帧的值。

  • 动画将使用由第二个关键帧指定的内插方法来创建第一个和第二个关键帧的 Value 之间的过渡。 过渡起始自第一个关键帧的 KeyTime,在到达第二个关键帧的 KeyTime 时结束。

  • 动画将继续,并创建每个后续关键帧及其前面的关键帧之间的过渡。

  • 最终,动画过渡到关键时间最大(等于或小于动画的 Duration)的关键帧值。

如果动画的 DurationAutomatic,或其 Duration 等于最后一个关键帧的时间,则动画将结束。 否则,如果动画的 Duration 大于最后一个关键帧的关键时间,则动画的关键帧值将一直保留,直到到达其 Duration 的末尾为止。 与所有动画类似,关键帧动画使用其 FillBehavior 属性确定在到达其活动周期末尾时是否保留最终值。 有关更多信息,请参见 计时行为概述

下面的示例使用在前面的示例中定义的 DoubleAnimationUsingKeyFrames 对象来演示 ValueKeyTime 属性的工作方式。

  • 第一个关键帧立即将动画的输出值设置为 0。

  • 第二个关键帧在 0 和 350 之间进行动画移动。 它的起始位置是第一个关键帧的结束位置(时间 = 0 秒),播放 2 秒钟,结束位置为时间 = 0:0:2。

  • 第三个关键帧在 350 和 50 之间进行动画移动。 它的起始位置是第二个关键帧的结束位置(时间 = 2 秒),播放 5 秒钟,结束位置为时间 = 0:0:7。

  • 第四个关键帧在 50 和 200 之间进行动画移动。 它的起始位置是第三个关键帧的结束位置(时间 = 7 秒),播放 1 秒钟,结束位置为时间 = 0:0:8。

  • 由于动画的 Duration 属性设置为 10 秒,该动画将其最终值保留两秒钟,并将在时间 = 0:0:10 时结束。

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
  WindowTitle="KeyFrame Animations">

  <Border Width="400" BorderBrush="Black">  

    <Rectangle Fill="Blue" 
      Width="50" Height="50"
      HorizontalAlignment="Left">
      <Rectangle.RenderTransform>
        <TranslateTransform 
          x:Name="MyAnimatedTranslateTransform" 
          X="0" Y="0" />
      </Rectangle.RenderTransform>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
          <BeginStoryboard>
            <Storyboard>

              <!-- Animate the TranslateTransform's X property
                   from 0 to 350, then 50,
                   then 200 over 10 seconds. -->

              <DoubleAnimationUsingKeyFrames
                Storyboard.TargetName="MyAnimatedTranslateTransform"
                Storyboard.TargetProperty="X"
                Duration="0:0:10">
                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
                <LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
                <LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
                <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />                          
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers> 
    </Rectangle>
  </Border> 
</Page>

内插方法

前面部分提到了某些关键帧动画支持多种内插方法。 动画的内插对动画在其持续时间内在值之间进行过渡的方式进行了描述。 通过选择您的动画将要使用哪种关键帧类型,您可以定义该关键帧段的内插方法。 有三种类型的内插方法:线性、离散和样条。

线性内插

使用线性内插,动画将以段持续期间内的固定速度来播放。 例如,如果关键帧段从 0 过渡到 10,持续期间为 5 秒,则动画会在指定时间输出以下值:

时间

输出值

0

0

1

2

2

4

3

6

4

8

4.25

8.5

4.5

9

5

10

离散内插

使用离散内插,动画函数将从一个值跳到下一个没有内插的值。 如果关键帧段从 0 过渡到 10,持续期间为 5 秒,则动画会在指定时间输出以下值:

时间

输出值

0

0

1

0

2

0

3

0

4

0

4.25

0

4.5

0

5

10

请注意,动画在段持续期间恰好结束之前不会更改其输出值。

样条内插更为复杂。 有关内容将在下一部分介绍。

样条内插

样条内插可用于达到更现实的计时效果。 由于动画通常用于模拟现实世界中发生的效果,因此开发人员可能需要精确地控制对象的加速和减速,并需要严格地对计时段进行操作。 通过样条关键帧,您可以使用样条内插进行动画处理。 使用其他关键帧,您可以指定一个 ValueKeyTime。 使用样条关键帧,您还可以指定一个 KeySpline。 下面的示例演示 DoubleAnimationUsingKeyFrames 的单个样条关键帧。 请注意 KeySpline 属性,它正是样条关键帧与其他类型的关键帧的不同之处。

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

一条三次方贝塞尔曲线由一个起点、一个终点和两个控制点来定义。 样条关键帧的 KeySpline 属性定义从 (0,0) 延伸到 (1,1) 的贝塞尔曲线的两个控制点。 第一个控制点控制贝塞尔曲线前半部分的曲线因子,第二个控制点控制贝塞尔线段后半部分的曲线因子。 所得到的曲线是对该样条关键帧的更改速率所进行的描述。 曲线陡度越大,关键帧更改其值的速度越快。 曲线趋于平缓时,关键帧更改其值的速度也趋于缓慢。

您可以使用 KeySpline 来模拟下落的水滴或跳动的球等的物理轨迹,或者应用动画的其他“潜入”和“潜出”效果。 对于用户交互效果,例如背景淡入/淡出或控制按钮弹跳等,您可能要应用样条内插,以便以特定方式提高或降低动画的更改速率。

以下示例将 KeySpline 指定为 0、1、1、0,可产生如下贝塞尔曲线。

控制点为 (0.0, 1.0) 和 (1.0, 0.0) 的关键样条

贝塞尔曲线

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

此关键帧将在开始时快速运动,减速,然后再次加速,直到结束。

以下示例将 KeySpline 指定为 0.5、0.25、0.75、1.0,可产生如下贝塞尔曲线。

控制点为 (0.25, 0.5) 和 (0.75, 1.0) 的关键样条

贝塞尔曲线

<SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  KeySpline="0.25,0.5 0.75,1" />

由于贝塞尔曲线的曲度变化幅度很小,此关键帧的运动速率几乎固定不变;只在将近接近结束时才开始减速。

下面的示例使用 DoubleAnimationUsingKeyFrames 对矩形的位置进行动画处理。 由于 DoubleAnimationUsingKeyFrames 使用 SplineDoubleKeyFrame 对象,每个关键帧值之间的过渡都将使用样条内插。

<!-- This rectangle is animated using a key frame animation
     with splined interpolation. -->
<Rectangle 
  Width="50"
  Height="50"
  Fill="Purple">  
  <Rectangle.RenderTransform>
    <TranslateTransform 
      x:Name="SplineAnimatedTranslateTransform" 
      X="0" Y="0" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>

          <!-- Animate the TranslateTransform's X property
               from its base value (0) to 500, then 200,
               then 350 over 15 seconds. -->
          <DoubleAnimationUsingKeyFrames
            Storyboard.TargetName="SplineAnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            Duration="0:0:15"
            RepeatBehavior="Forever">                
            <SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

            <SplineDoubleKeyFrame Value="200" KeyTime="0:0:10"  KeySpline="0.0,0.0 1.0,0.0" />

            <SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  KeySpline="0.25,0.5 0.75,1" />
          </DoubleAnimationUsingKeyFrames>           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers> 
</Rectangle>

样条内插可能很难理解;请使用不同的设置进行体验,这会有助于理解。 通过 Key Spline Animation Sample(关键样条动画示例),可以更改关键样条值,并可查看由此所产生的动画结果。

组合内插方法

您可在一个关键帧动画中使用具有不同内插类型的关键帧。 如果两个具有不同内插的关键帧动画彼此跟随,第二个关键帧的内插方法将用于创建从第一个值到第二个值的过渡。

以下示例将创建一个使用线性、样条和离散内插的 DoubleAnimationUsingKeyFrames

<!-- This rectangle is animated using a key frame animation
     with a combination of interpolation methods. -->
<Rectangle 
  Width="50"
  Height="50"
  Fill="Orange">  
  <Rectangle.RenderTransform>
    <TranslateTransform 
      x:Name="ComboAnimatedTranslateTransform" 
      X="0" Y="0" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>

          <!-- Animate the TranslateTransform's X property
               from its base value (0) to 500, then 200,
               then 350 over 15 seconds. -->
          <DoubleAnimationUsingKeyFrames
            Storyboard.TargetName="ComboAnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            Duration="0:0:15"
            RepeatBehavior="Forever">
            <DiscreteDoubleKeyFrame Value="500" KeyTime="0:0:7" />
            <LinearDoubleKeyFrame Value="200" KeyTime="0:0:10" />
            <SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  
              KeySpline="0.25,0.5 0.75,1" />                      
          </DoubleAnimationUsingKeyFrames>           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers> 
</Rectangle>

有关持续时间和关键时间的更多信息

像其他动画一样,关键帧动画具有 Duration 属性。 除了指定动画的 Duration 外,您还需要指定向每个关键帧分配持续时间内的多长一段时间。 您可以为动画的每个关键帧描述其 KeyTime 来实现此目的。 每个关键帧的 KeyTime 都指定了该关键帧的结束时间。

KeyTime 属性并不指定关键时间播放的长度。 关键帧播放时间长度由关键帧的结束时间、前一个关键帧的结束时间以及动画的持续时间来确定。 可以以时间值、百分比的形式来指定关键时间,或者将其指定为特殊值 UniformPaced

以下列表描述了指定关键时间的不同方式。

TimeSpan 值

您可以使用 TimeSpan 值来指定 KeyTime。 该值应大于或等于 0 并且小于或等于动画的持续时间。 下面的示例演示一个持续时间为 10 秒钟、有四个关键帧(这些关键帧的关键时间被指定为时间值)的动画。

  • 在前 3 秒钟内,第一个关键帧将在基值和 100 之间进行动画移动。结束位置为时间 = 0:0:03。

  • 第二个关键帧在 100 和 200 之间进行动画移动。 它的起始位置是第一个关键帧的结束位置(时间 = 3 秒),播放 5 秒钟,结束位置为时间 = 0:0:8。

  • 第三个关键帧在 200 和 500 之间进行动画移动。 它的起始位置是第二个关键帧的结束位置(时间 = 8 秒),播放 1 秒钟,结束位置为时间 = 0:0:9。

  • 第四个关键帧在 500 和 600 之间进行动画移动。 它的起始位置是第三个关键帧的结束位置(时间 = 9 秒),播放 1 秒钟,结束位置为时间 = 0:0:10。

<!-- This rectangle is animated with KeyTimes using TimeSpan values. 
     Goes to 100 in the first 3 seconds, 100 to 200 in 
     the next 5 seconds, 300 to 500 in the next second,
     and 500 to 600 in the final second. -->
<Rectangle Width="50" Height="50" Fill="Blue">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform01" X="10" Y="30" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform01" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed as TimeSpan values 
                 which are in the form of "hours:minutes:seconds". -->
            <LinearDoubleKeyFrame Value="100" KeyTime="0:0:3" />
            <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />
            <LinearDoubleKeyFrame Value="500" KeyTime="0:0:9" />
            <LinearDoubleKeyFrame Value="600" KeyTime="0:0:10" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

百分比值

百分比值指定关键帧在动画的 Duration 内的某百分比处结束。 在 XAML 中,将百分比指定为一个数字,后面跟随 % 符号。 在代码中,使用 FromPercent 方法并向其传递一个 Double,以表示百分比。 该值必须大于或等于 0 并且小于或等于 100%。 下面的示例演示一个持续时间为 10 秒钟、有四个关键帧(这些关键帧的关键时间被指定为百分比)的动画。

  • 在前 3 秒钟内,第一个关键帧将在基值和 100 之间进行动画移动,结束位置为时间 = 0:0:3。

  • 第二个关键帧在 100 和 200 之间进行动画移动。 它的起始位置是第一个关键帧的结束位置(时间 = 3 秒),播放 5 秒钟,结束位置为时间 = 0:0:8 (0.8 * 10 = 8)。

  • 第三个关键帧在 200 和 500 之间进行动画移动。 它的起始位置是第二个关键帧的结束位置(时间 = 8 秒),播放 1 秒钟,结束位置为时间 = 0:0:9 (0.9 * 10 = 9)。

  • 第四个关键帧在 500 和 600 之间进行动画移动。 它的起始位置是第三个关键帧的结束位置(时间 = 9 秒),播放 1 秒钟,结束位置为时间 = 0:0:10 (1 * 10 = 10)。

<!-- Identical animation behavior to the previous rectangle 
     but using percentage values for KeyTimes rather then TimeSpan. -->
<Rectangle Height="50" Width="50" Fill="Purple">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform02" X="10" Y="110" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform02" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed as Percentages. -->
            <LinearDoubleKeyFrame Value="100" KeyTime="30%" />
            <LinearDoubleKeyFrame Value="200" KeyTime="80%" />
            <LinearDoubleKeyFrame Value="500" KeyTime="90%" />
            <LinearDoubleKeyFrame Value="600" KeyTime="100%" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

特殊值 Uniform

如果希望每个关键帧的持续时间都相同,请使用 Uniform 计时。

Uniform 关键时间按关键帧的数量平均分配可用时间,以确定每个关键帧的结束时间。 下面的示例演示一个持续时间为 10 秒钟、有四个关键帧(这些关键帧的关键时间被指定为 Uniform)的动画。

  • 在前 2.5 秒钟内,第一个关键帧将在基值和 100 之间进行动画移动,结束位置为时间 = 0:0:2.5。

  • 第二个关键帧在 100 和 200 之间进行动画移动。 它的起始位置是第一个关键帧的结束位置(时间 = 2.5 秒),播放大约 2.5 秒钟,结束位置为时间 = 0:0:5。

  • 第三个关键帧在 200 和 500 之间进行动画移动。 它的起始位置是第二个关键帧的结束位置(时间 = 5 秒),播放 2.5 秒钟,结束位置为时间 = 0:0:7.5。

  • 第四个关键帧在 500 和 600 之间进行动画移动。 它的起始位置是第二个关键帧的结束位置(时间 = 7.5 秒),播放 2.5 秒钟,结束位置为时间 = 0:0:1。

<!-- This rectangle is animated with KeyTimes using Uniform values.  -->
<Rectangle Height="50" Width="50" Fill="Red">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform03" X="10" Y="190" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform03" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed with values of Uniform. 
                 When a key time is set to "Uniform" the total allotted 
                 time of the animation is divided evenly between key frames.  
                 In this example, the total duration of the animation is 
                 ten seconds and there are four key frames each of which 
                 are set to "Uniform", therefore, the duration of each key frame 
                 is 3.3 seconds (10/3). -->
            <LinearDoubleKeyFrame Value="100" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="200" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="500" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="600" KeyTime="Uniform" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

特殊值 Paced

如果希望以固定速率显示动画,请使用 Paced 计时。

Paced 关键时间根据每一关键帧的长度来分配可用时间,以确定每帧的持续时间。 这样,动画的速度或速率将保持不变。 下面的示例演示一个持续时间为 10 秒钟、有三个关键帧(这些关键帧的关键时间被指定为 Paced)的动画。

<!-- Using Paced Values. Rectangle moves between key frames at 
     uniform rate except for first key frame
     because using a Paced value on the first KeyFrame in a 
     collection of frames gives a time of zero. -->
<Rectangle Height="50" Width="50" Fill="Orange">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform04" X="10" Y="270" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform04" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed with values of Paced. 
                 Paced values are used when a constant rate is desired. 
                 The time allocated to a key frame with a KeyTime of "Paced" 
                 is determined by the time allocated to the other key 
                 frames of the animation. This time is calculated to 
                 attempt to give a "paced" or "constant velocity" 
                 for the animation. -->
            <LinearDoubleKeyFrame Value="100" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="200" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="500" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="600" KeyTime="Paced" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

请注意,如果最后一个关键帧的关键时间为 PacedUniform,其解析的关键时间将设置为 100%。 如果多帧动画中的第一个关键帧为固定速度,则其解析的关键时间将设置为 0。 如果关键帧集合仅包含单个关键帧,并且是一个固定速度的关键帧,则其解析的关键时间将设置为 100%。

一个关键帧动画中的不同关键帧可使用不同的关键时间类型。

组合关键时间,顺序紊乱的关键帧

您可在同一动画中使用具有不同 KeyTime 值类型的关键帧。 此外,我们建议您以关键帧的预期播放顺序来添加关键帧,但也可不必这么操作。 动画和计时系统能够处理顺序紊乱的关键帧。 将忽略具有无效关键时间的关键帧。

以下列表描述了为关键帧动画的关键帧解析关键时间的过程。

  1. 解析 TimeSpan KeyTime 值。

  2. 确定动画的总内插时间,即关键帧动画完成向前迭代所需的全部时间。

    1. 如果动画的 Duration 不是 AutomaticForever,则总内插时间为动画的 Duration 属性的值。

    2. 否则,总内插时间是其关键帧中所指定的最大 TimeSpan KeyTime 值(如果存在这样的值)。

    3. 否则,总内插时间为 1 秒。

  3. 使用总内插时间值解析 Percent KeyTime 值。

  4. 如果最后一个关键帧尚未在前面的步骤中解析,则将解析该关键帧。 如果最后一个关键帧的 KeyTimeUniformPaced,其解析的时间将等于总内插时间。

    如果第一个关键帧的 KeyTimePaced,并且此动画具有多个关键帧,则将其 KeyTime 值解析为零;如果只有一个关键帧,并且其 KeyTime 值为 Paced,则该值将解析为总内插时间,如前面的步骤所述。

  5. 解析其余的 Uniform KeyTime 值:它们将平均分配可用时间。 在此过程中,未解析的 Paced KeyTime 值将被临时视为 Uniform KeyTime 值,并将获得临时解析时间。

  6. 解析具有未指定关键时间的关键帧的 KeyTime 值,具体做法是使用距离它们最近的、已解析 KeyTime 值的声明关键帧。

  7. 解析其余的 Paced KeyTime 值。 Paced KeyTime 使用临近关键帧的 KeyTime 值确定其解析时间。 目标是确保动画速度在此关键帧的解析时间内保持固定不变。

  8. 将关键帧按解析时间(主键)以及声明顺序(次键)进行排序,换言之,根据解析关键帧 KeyTime 值按固定顺序进行排序。

请参见

参考

KeyTime

KeySpline

Timeline

概念

动画概述

演示图板概述

计时行为概述

其他资源

Key Spline Animation Sample

KeyFrame Animation Sample

关键帧动画帮助主题