本主题介绍关键帧动画。 关键帧动画使你能够使用两个以上的目标值进行动画处理,并控制动画的内插方法。
先决条件
若要了解此概述,应熟悉 Windows Presentation Foundation(WPF)动画和时间线。 有关动画的简介,请参阅 动画概述。 它还有助于熟悉 From/To/By 动画。 有关详细信息,请参阅 From/To/By 动画概述。
什么是 Key-Frame 动画?
与 From/To/By 动画一样,关键帧动画对目标属性的值进行动画处理。 ** 它在其Duration之间创建目标值的转换。 但是,当 From/To/By 动画在两个值之间创建过渡时,单个关键帧动画可以在任意数量的目标值之间创建转换。 与 From/To/By 动画不同,关键帧动画没有用于设置其目标值的 From、To 或 By 属性。 关键帧动画的目标值使用关键帧对象(因此术语“关键帧动画”)进行描述。 若要指定动画的目标值,请创建关键帧对象并将其添加到动画的 KeyFrames 集合中。 动画运行时,它会在指定的帧之间切换。
除了支持多个目标值之外,某些关键帧方法甚至还支持多个内插方法。 动画的内插方法决定了如何从一个值过渡到下一个值。 有三种类型的内插:离散、线性和样条。
若要使用关键帧动画进行动画处理,请完成以下步骤。
以下示例使用DoubleAnimationUsingKeyFrames来将Rectangle元素动画到四个不同的位置。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://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>
与 From/To/By 动画一样,关键帧动画可以通过在标记中使用 Storyboard 或在代码中使用 BeginAnimation 方法来应用于属性。 还可以使用关键帧动画来创建 AnimationClock 并将其应用于一个或多个属性。 有关应用动画的不同方法的详细信息,请参阅 属性动画技术概述。
Key-Frame 动画类型
由于动画生成属性值,因此不同的属性类型有不同的动画类型。 若要对采用 Double (如元素 Width 属性)的属性进行动画处理,请使用生成 Double 值的动画。 若要对采用属性 Point的属性进行动画处理,请使用生成 Point 值的动画等。
关键帧动画类属于 System.Windows.Media.Animation 命名空间,并遵循以下命名约定:
<类型>AnimationUsingKeyFrames
其中 <Type> 是类动画的值的类型。
WPF 提供以下关键帧动画类。
属性类型 | 对应的起/止/按动画类 | 支持的插值方法 |
---|---|---|
Boolean | BooleanAnimationUsingKeyFrames | 离散 |
Byte | ByteAnimationUsingKeyFrames | 离散、线性、样条 |
Color | ColorAnimationUsingKeyFrames | 离散、线性、样条 |
Decimal | DecimalAnimationUsingKeyFrames | 离散、线性、样条化 |
Double | DoubleAnimationUsingKeyFrames | 离散、线性、Splined |
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 | 离散、线性、Splined |
Vector3D | Vector3DAnimationUsingKeyFrames | 离散、线性、样条 |
Vector | VectorAnimationUsingKeyFrames | 离散、线性、样条 |
目标值(关键帧)和关键时间
正如有不同类型的关键帧动画用于生成不同属性类型的动画效果一样,也存在不同类型的关键帧对象:每种类型的值动画以及所支持的内插方法都有对应的关键帧对象。 关键帧类型遵循以下命名约定:
<InterpolationMethod><类型>KeyFrame
其中 <内插方法> 是关键帧使用的插值方法,<类型> 是类动画的值的类型。 支持所有三种内插方法的关键帧动画将具有可以使用的三个关键帧类型。 例如,可以使用与DoubleAnimationUsingKeyFrames相关的三个关键帧类型: DiscreteDoubleKeyFrame、LinearDoubleKeyFrame,以及 SplineDoubleKeyFrame。 (稍后的部分将详细介绍内插方法。)
关键帧的主要用途是指定 a KeyTime 和 a Value. 每个关键帧类型都提供这两个属性。
关键帧动画开始时,按照其关键帧属性定义的顺序依次处理各个关键帧。
如果时间 0 时没有关键帧,动画将在目标属性的当前值与 Value 第一个关键帧之间创建转换;否则,动画的输出值将成为第一个关键帧的值。
该动画使用第二个关键帧指定的内插方法,在第一个关键帧和第二个关键帧之间创建Value的转换。 切换从第一个关键帧开始 KeyTime ,到达第二个关键帧 KeyTime 时结束。
动画继续,在每个后续关键帧及其前面的关键帧之间创建切换。
最后,动画将转换为关键帧的值,其关键时间大于或小于动画的 Duration键时间。
如果动画 Duration 是 Automatic 或其 Duration 等于最后一个关键帧的时间,则动画结束。 否则,如果动画 Duration 大于最后一个关键帧的关键时间,则动画将保留关键帧值,直到它到达其 Duration末尾。 与所有动画一样,关键帧动画使用其 FillBehavior 属性来确定它是否在到达活动期结束时保留其最终值。 有关详细信息,请参阅 计时行为概述。
以下示例使用 DoubleAnimationUsingKeyFrames 在前面的示例中定义的对象来演示 Value 和 KeyTime 属性的工作原理。
第一个关键帧会立即将动画的输出值设置为 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 之前保留其最终值 2 秒。
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://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>
内插方法
前面的部分提到,一些关键帧动画支持多个插值方法。 动画的内插描述动画在其持续时间内如何转换值。 通过选择与动画一起使用的关键帧类型,可以定义该关键帧段的内插方法。 有三种不同类型的内插方法:线性、离散和样条。
线性插值
使用线性插值时,动画以与段持续时间一致的固定速率进行。 例如,如果关键帧段在 5 秒的持续时间内从 0 转换到 10,动画将在指定时间输出以下值:
时间 | 输出值 |
---|---|
0 | 0 |
1 | 2 |
2 | 4 |
3 | 6 |
4 | 8 |
4.25 | 8.5 |
4.5 | 9 |
5 | 10 |
离散插值
使用离散内插时,动画函数从一个值跳转到下一个值,而无需内插。 如果关键帧段在 5 秒的持续时间内从 0 转换到 10,动画将在指定时间输出以下值:
时间 | 输出值 |
---|---|
0 | 0 |
1 | 0 |
2 | 0 |
3 | 0 |
4 | 0 |
4.25 | 0 |
4.5 | 0 |
5 | 10 |
请注意动画在段持续时间结束前不会更改其输出值的方式。
样条插值更为复杂。 下一部分将介绍它。
样条插值
样条插值可用于实现更真实的时间效果。 由于动画经常用于模仿现实世界中出现的效果,因此开发人员可能需要对对象的加速和减速进行精细控制,并对时间段进行精细操控。 通过样条关键帧,您可以使用样条插值进行动画。 使用其他关键帧,您可以指定Value和KeyTime。 使用样条关键帧时,您还可以指定一个 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,用于创建以下 Bezier 曲线。
具有控制点(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,用于创建以下 Bezier 曲线。
具有控制点(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>
可能难以理解 Splined 内插;尝试不同的设置可能会有所帮助。 通过关键样条动画示例,您可以更改关键样条值,并观察其对动画的影响。
组合内插方法
可以在单个关键帧动画中使用具有不同内插类型的关键帧。 当具有不同内插的两个关键帧动画相互跟踪时,第二个关键帧的内插方法用于创建从第一个值到第二个值的转换。
在以下示例中,创建了一个使用线性、样条和离散插值的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 属性不指定关键时间的播放时间。 关键帧播放的时间量取决于关键帧何时结束、上一个关键帧结束以及动画的持续时间。 键时间可以指定为时间值、百分比或特殊值 Uniform 或 Paced。
以下列表描述了指定键时间的不同方式。
时间跨度值
可以使用 TimeSpan 值来指定一个 KeyTime。 该值应大于或等于 0,并且小于或等于动画的持续时间。 以下示例显示了一个持续时间为 10 秒和四个关键帧的动画,关键时间指定为时间值。
第一个关键帧从基值过渡到100,用时3秒,结束于0:0:03。
第二个关键帧动画从 100 到 200。 它在第一个关键帧结束(时间 = 3 秒)后开始,播放 5 秒,结束时间 = 0:0:8。
第三个关键帧的动画从 200 到 500。 第二个关键帧结束时(时间 = 8 秒)开始播放,持续 1 秒,结束时间为 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 秒和 4 个关键帧的动画,关键时间指定为百分比。
第一个关键帧在前 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 时间将可用时间相等除以关键帧数,以确定每个关键帧的结束时间。 下面的示例演示了一个动画,其持续时间为 10 秒和 4 个关键帧,其关键时间指定为 Uniform。
第一个关键帧在前2.5秒内从基值变为100,结束于时间0:0:2.5。
第二个关键帧的动画效果从 100 转变到 200。 它在第一个关键帧结束(时间 = 2.5 秒)后开始,播放大约 2.5 秒,结束时间 = 0:0:5。
第三个关键帧的动画从 200 变化到 500。 在第二个关键帧结束时(时间 = 5 秒)开始播放,持续 2.5 秒,结束时间为 0:00: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关键时间根据每个关键帧的长度分配可用时间,以确定每个帧的持续时间。 这将提供动画速度或节奏保持不变的效果。 以下示例显示了一个持续时间为 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>
请注意,如果最后一个关键帧的关键时间是 Paced 或 Uniform,其解析的关键时间将设置为 100%。 如果多帧动画中的第一个关键帧设定了节奏,其解析的关键时间将设置为0。 (如果关键帧集合仅包含单个关键帧,并且它是节拍关键帧,则其解析后的关键时间将设置为 100%。)
单个关键帧动画中的不同关键帧可能使用不同的关键时间类型。
组合关键时刻、输出Of-Order 关键帧
可以在同一动画中使用具有不同 KeyTime 值类型的关键帧。 而且,尽管建议按照关键帧的播放顺序添加关键帧,但这并不是必须的。 动画和计时系统能够解析无序关键帧。 关键帧的无效关键时间将被忽略。
以下列表描述了解析关键帧动画中关键时间的过程。
确定动画的总内插时间,即关键帧动画完成一次向前迭代所需的总时间。
解决上一个关键帧(如果尚未在前面的步骤中解析)。 KeyTime如果最后一个关键帧是Uniform或Paced,其解析时间将等于总内插时间。
如果第一个关键帧的KeyTime是Paced,且这个动画有多个关键帧,则其KeyTime值被解析为零;如果只有一个关键帧且其KeyTime值为Paced,则解析为上一步中所述的总插值时间。
解决剩余 UniformKeyTime 值:每个值都给定可用时间的相同份额。 在此过程中,未解析 PacedKeyTime 的值将暂时视为 UniformKeyTime 值,并获取临时解析时间。
解析剩余 PacedKeyTime 值。 Paced KeyTime KeyTime使用相邻关键帧的值来确定其解析时间。 目标是确保动画的速度在此关键帧的解析时间周围保持不变。
按解析时间(主键)和声明顺序(辅助键)对关键帧进行排序,即基于解析的关键帧 KeyTime 值使用稳定的排序。