# Key-Frame Animations Overview

This topic introduces you to key-frame animations. Key-frame animations enable you to animate using more than two target values, and control an animation's interpolation method.

## Prerequisites

To understand this overview, you should be familiar with Windows Presentation Foundation (WPF) animations and timelines. For an introduction to animations, see the Animation Overview. It also helps to be familiar with From/To/By animations. For more information, see the From/To/By Animations Overview.

## What is a Key-Frame Animation?

Like a From/To/By animation, a key-frame animation animates the value of a target property. It creates a transition among its target values over its Duration. However, while a From/To/By animation creates a transition between two values, a single key-frame animation can create transitions among any number of target values. Unlike a From/To/By animation, a key frame animation has no From, To, or By properties with which to set its target values. A key-frame animation's target values are described using key frames objects (hence the term, "key-frame animation"). To specify the animation's target values, you create key frame objects and add them to the animation's KeyFrames collection. When the animation runs, it transitions between the frames you specified.

In addition to supporting multiple target values, some key-frame methods even support multiple interpolation methods. An animation's interpolation method defines how it transitions from one value to the next. There are three types of interpolations: discrete, linear, and splined.

To animate with a key-frame animation, you complete the following steps.

• Declare the animation and specify its Duration, just like you would for a from/to/by animation.

• For each target value, create a key frame of the appropriate type, set its value and KeyTime, and add it to the animation's KeyFrames collection.

• Associate the animation with a property, just like you would with a From/To/By animation. For more information about applying an animation to a property using a storyboard, see Storyboards Overview.

The following example uses a DoubleAnimationUsingKeyFrames to animate a Rectangle element to four different locations.

<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>


Like a From/To/By animation, a key-frame animation can be applied to a property by using a Storyboard in markup and code or by using the BeginAnimation method in code. You may also use a key-frame animation to create an AnimationClock and apply it to one or more properties. For more information about the different methods for applying animations, see the Property Animation Techniques Overview.

## Key-Frame Animation Types

Because animations generate property values, there are different animation types for different property types. To animate a property that takes a Double (such as an element's Width property), you use an animation that produces Double values. To animate a property that takes a Point, you use an animation that produces Point values, and so on.

The key-frame animation classes belong to the System.Windows.Media.Animation namespace and adhere to the following naming convention:

<Type> AnimationUsingKeyFrames

Where <Type> is the type of value that the class animates.

WPF provides the following key-frame animation classes.

Property type Corresponding from/to/by animation class Interpolation methods supported
Boolean BooleanAnimationUsingKeyFrames Discrete
Byte ByteAnimationUsingKeyFrames Discrete, Linear, Splined
Color ColorAnimationUsingKeyFrames Discrete, Linear, Splined
Decimal DecimalAnimationUsingKeyFrames Discrete, Linear, Splined
Double DoubleAnimationUsingKeyFrames Discrete, Linear, Splined
Int16 Int16AnimationUsingKeyFrames Discrete, Linear, Splined
Int32 Int32AnimationUsingKeyFrames Discrete, Linear, Splined
Int64 Int64AnimationUsingKeyFrames Discrete, Linear, Splined
Matrix MatrixAnimationUsingKeyFrames Discrete
Object ObjectAnimationUsingKeyFrames Discrete
Point PointAnimationUsingKeyFrames Discrete, Linear, Splined
Quaternion QuaternionAnimationUsingKeyFrames Discrete, Linear, Splined
Rect RectAnimationUsingKeyFrames Discrete, Linear, Splined
Rotation3D Rotation3DAnimationUsingKeyFrames Discrete, Linear, Splined
Single SingleAnimationUsingKeyFrames Discrete, Linear, Splined
String StringAnimationUsingKeyFrames Discrete
Size SizeAnimationUsingKeyFrames Discrete, Linear, Splined
Thickness ThicknessAnimationUsingKeyFrames Discrete, Linear, Splined
Vector3D Vector3DAnimationUsingKeyFrames Discrete, Linear, Splined
Vector VectorAnimationUsingKeyFrames Discrete, Linear, Splined

## Target Values (key frames) and Key Times

Just as there are different types of key-frame animations for animating different property types, there are also different types of key frame objects: one for each type of value animated and interpolation method supported. Key frame types adhere to the following naming convention:

<InterpolationMethod><Type> KeyFrame

Where <InterpolationMethod> is the interpolation method the key frame uses and <Type> is the type of value that the class animates. A key-frame animation that supports all three interpolation methods will have three key frame types that you can use. For example, you can use three key frame types with a DoubleAnimationUsingKeyFrames: DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, and SplineDoubleKeyFrame. (Interpolation methods are described in detail in a later section.)

The primary purpose of a key frame is to specify a KeyTime and a Value. Every key frame type provides these two properties.

• The Value property specifies the target value for that key-frame.

• The KeyTime property specifies when (within the animation's Duration) a key frame's Value is reached.

When a key frame animation begins, iterates through its key frames in the order defined by their KeyTime properties.

• If there is no key frame at time 0, the animation creates a transition between the target property's current value and the Value of the first key frame; otherwise, the animation's output value becomes the value of the first key frame.

• The animation creates a transition between the Value of the first and second key frames using the interpolation method specified by the second key frame. The transition starts at the first key frame's KeyTime and ends when the second key frame's KeyTime is reached.

• The animation continues, creating transitions between each subsequent key frame and its preceding key frame.

• Finally, the animation transitions to the value of the key frame with the greatest key time that is equal to or smaller than the animation's Duration.

If the animation's Duration is Automatic or its Duration is equal to the time of the last key frame, the animation ends. Otherwise, if the animation's Duration is greater than the key time of the last key frame, the animation holds the key frame value until it reaches the end of its Duration. Like all animations, a key-frame animation uses its FillBehavior property to determine whether it holds it final value when it reaches the end of its active period. For more information, see the Timing Behaviors Overview.

The following example uses the DoubleAnimationUsingKeyFrames object defined in the preceding example to demonstrate how the Value and KeyTime properties work.

• The first key frame immediately sets the animation's output value to 0.

• The second key frame animates from 0 to 350. It starts after the first key frame ends (at time = 0 seconds) and plays for 2 seconds, ending at time = 0:0:2.

• The third key frame animates from 350 to 50. It starts when the second key frame ends (at time = 2 seconds) and plays for 5 seconds, ending at time = 0:0:7.

• The fourth key frame animates from 50 to 200. It starts when the third key frame ends (at time = 7 seconds) and plays for 1 second, ending at time = 0:0:8.

• Because the Duration property of the animation was set to 10 seconds, the animation holds its final value for two seconds before ending at time = 0:0:10.

<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>


## Interpolation Methods

The preceding sections mentioned that some key-frame animations support multiple interpolation methods. An animation's interpolation describes how an animation transitions between values over its duration. By selecting which key frame type you use with your animation, you can define the interpolation method for that key frame segment. There are three different types of interpolation methods: linear, discrete, and splined.

### Linear Interpolation

With linear interpolation, the animation progresses at a constant rate of the segment duration. For example, if a key frame segment transitions from 0 to 10 over a duration of 5 seconds, the animation will output the following values at the specified times:

Time Output value
0 0
1 2
2 4
3 6
4 8
4.25 8.5
4.5 9
5 10

### Discrete Interpolation

With discrete interpolation, the animation function jumps from one value to the next without interpolation. If a key frame segment transitions from 0 to 10 over a duration of 5 seconds, the animation will output the following values at the specified times:

Time Output value
0 0
1 0
2 0
3 0
4 0
4.25 0
4.5 0
5 10

Notice how the animation does not change its output value until the very end of the segment duration.

Splined interpolation is more complex. It is described in the next section.

### Splined Interpolation

Splined interpolation can be used to achieve more realistic timing effects. Because animations are so often used to imitate effects that occur in the real world, developers might need fine control of the acceleration and deceleration of objects, and close manipulation of timing segments. Spline key frames enable you to animate with splined interpolation. With other key frames, you specify a Value and KeyTime. With a spline key frame, you also specify a KeySpline. The following example shows a single spline key frame for a DoubleAnimationUsingKeyFrames. Notice the KeySpline property; that's what makes a spline key frame different from the other types of key frames.

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


A cubic Bezier curve is defined by a start point, an end point, and two control points. The KeySpline property of a spline key frame defines the two control point of a Bezier curve that extends from (0,0) to (1,1). The first control point controls the curve factor of the first half of the Bezier curve, and the second control point controls the curve factor of the second half of the Bezier segment. The resulting curve describes the rate of change for that spline key frame. The steeper the curve, the faster the key frame changes its values. As the curve gets flatter, the key frame changes its values more slowly.

You might use KeySpline to simulate physical trajectories like falling water or bouncing balls, or apply other "ease in" and "ease out" effects to motion animations. For user interaction effects like background fades or control button rebound, you might apply splined interpolation to speed up or slow down the rate of change for an animation in a specific way.

The following example specifies a KeySpline of 0,1 1,0, which creates the following Bezier curve.

A key spline with control points (0.0, 1.0) and (1.0, 0.0)

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


This key frame animates rapidly when it begins, slows down, and then speeds up again before it ends.

The following example specifies a KeySpline of 0.5,0.25 0.75,1.0, which creates the following Bezier curve.

A key spline with control points (0.25, 0.5) and (0.75, 1.0)

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


Because the curvature of the Bezier curve changes very little, this key frame animates at an almost constant rate; it slows down somewhat toward its very end.

The following example uses a DoubleAnimationUsingKeyFrames to animate the position of rectangle. Because the DoubleAnimationUsingKeyFrames uses SplineDoubleKeyFrame objects, the transition between each key frame value uses splined interpolation.

<!-- 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>
<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 interpolation can be difficult to understand; experimenting with different settings can help. The Key Spline Animation Sample enables you to change key spline values and see the result it has on an animation.

### Combining Interpolation Methods

You can use key frames with different interpolation types in a single key frame animation. When two key frame animations with different interpolations follow each other, the interpolation method of the second key frame is used to create the transition from the first value to the second.

In the following example, a DoubleAnimationUsingKeyFrames is created that uses linear, splined, and discrete interpolation.

<!-- 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>
<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>


## More about Duration and Key Times

Like other animations, key-frame animations have a Duration property. In addition to specifying the animation's Duration, you need to specify what portion of that duration is given to each key frame. You do so by describing a KeyTime for each of the animation's key frames. Each key frame's KeyTime specifies when that key frame ends.

The KeyTime property does not specify how long the key time plays. The amount of time a key frame plays is determined by when the key frame ends, when the previous key frame ended, and the animation's duration. Key times may be specified as a time value, a percentage, or as the special values Uniform or Paced.

The following list describes the different ways of specifying key times.

### TimeSpan Values

You may use TimeSpan values to specify a KeyTime. The value should be greater than or equal to 0 and less than or equal to the animation's duration. The following example shows an animation with a duration of 10 seconds and four key frames whose key times are specified as time values.

• The first key frame animates from the base value to 100 over the first 3 seconds, ending at time = 0:0:03.

• The second key frame animates from 100 to 200. It starts after the first key frame ends (at time = 3 seconds) and plays for 5 seconds, ending at time = 0:0:8.

• The third key frame animates from 200 to 500. It starts when the second key frame ends (at time = 8 seconds) and plays for 1 second, ending at time = 0:0:9.

• The fourth key frame animates from 500 to 600. It starts when the third key frame ends (at time = 9 seconds) and plays for 1 second, ending at time = 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>
<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>


### Percentage Values

A percentage value specifies that the key frame ends at some percentage of the animation's Duration. In XAML, you specify the percentage as a number followed by the % symbol. In code, you use the FromPercent method and pass it a Double indicating the percentage. The value must be greater than or equal to 0 and less than or equal to 100 percent. The following example shows an animation with a duration of 10 seconds and four key frames whose key times are specified as percentages.

• The first key frame animates from the base value to 100 over the first 3 seconds, ending at time = 0:0:3.

• The second key frame animates from 100 to 200. It starts after the first key frame ends (at time = 3 seconds) and plays for 5 seconds, ending at time = 0:0:8 (0.8 * 10 = 8).

• The third key frame animates from 200 to 500. It starts when the second key frame ends (at time = 8 seconds) and plays for 1 second, ending at time = 0:0:9 (0.9 * 10 = 9).

• The fourth key frame animates from 500 to 600. It starts when the third key frame ends (at time = 9 seconds) and plays for 1 second, ending at time = 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>
<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>


### Special Value, Uniform

Use Uniform timing when you want each key frame to take the same amount of time.

A Uniform key time divides the available time equally by the number of key frames to determine the end time of each key frame. The following example shows an animation with a duration of 10 seconds and four key frames whose key times are specified as Uniform.

• The first key frame animates from the base value to 100 over the first 2.5 seconds, ending at time = 0:0:2.5.

• The second key frame animates from 100 to 200. It starts after the first key frame ends (at time = 2.5 seconds) and plays for approximately 2.5 seconds, ending at time = 0:0:5.

• The third key frame animates from 200 to 500. It starts when the second key frame ends (at time = 5 seconds) and plays for 2.5 seconds, ending at time = 0:0:7.5.

• The fourth key frame animates from 500 to 600. It starts when the second key frame ends (at time = 7.5 seconds) and plays for 2.5 seconds, ending at time = 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>
<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>


### Special Value, Paced

Use Paced timing when you want to animate at a constant rate.

A Paced key time allocates the available time according to the length of each of the key frames to determine the duration of each frame. This will provide the behavior that the velocity or pace of the animation remains constant. The following example shows an animation with a duration of 10 seconds and three key frames whose key times are specified as 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>
<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>


Note that, if the last key frame's key time is Paced or Uniform, its resolved key time will be set to 100 percent. If the first key frame in a multiframe animation is paced, its resolved key time will be set to 0. (If the key frame collection contains only a single key frame and it is a paced key frame, its resolved key time will be set to 100 percent.)

Different key frames within a single key frame animation may use different key time types.

## Combining Key Times, Out-Of-Order Key Frames

You can use key frames with different KeyTime value types in the same animation. And, although it's recommended that you add key frames in the order in which they should play, it's not necessary. The animation and timing system is capable of resolving out of order key frames. Key frames with invalid key times are ignored.

The following list describes the procedure by which key times are resolved for a key-frame animation's key frames.

1. Resolve TimeSpan KeyTime values.

2. Determine the animation’s total interpolation time, the total time it takes the key-frame animation to complete a forward iteration.

1. If the animation's Duration is not Automatic or Forever, the total interpolation time is the value of the animation's Duration property.

2. Otherwise, the total interpolation time is the largest TimeSpan KeyTime value specified among its key frames, if any exist.

3. Otherwise, the total interpolation time is 1 second.

3. Use the total interpolation time value to resolve Percent KeyTime values.

4. Resolve last key frame, if it wasn't already resolved in the previous steps. If the KeyTime of the last key frame is Uniform or Paced, its resolved time will be equal to the total interpolation time.

If the KeyTime of the first key frame is Paced and this animation has more than on key frames, resolve its KeyTime value to zero; if there is only one key frame and its KeyTime value is Paced, it is resolved to the total interpolation time, as described in the preceding step.

5. Resolve remaining Uniform KeyTime values: they are each given an equal share of the available time. During this process, unresolved Paced KeyTime values are temporarily treated as Uniform KeyTime values, and get a temporary resolved time.

6. Resolve the KeyTime values of key frames with unspecified key times by using the key frames declared nearest them that have resolved KeyTime values.

7. Resolve remaining Paced KeyTime values. Paced KeyTime use the KeyTime values of the neighboring key frames to determine their resolved time. The goal is to ensure that the velocity of the animation is constant around this key frame's resolved time.

8. Sort key frames in order of resolved time (primary key), and order of declaration (secondary key), i.e., use a stable sort based on the resolved key frame KeyTime values.