A key frame animation's target values are defined by its KeyFrames property, which contains a collection of ByteKeyFrame objects. Each ByteKeyFrame defines a segment of the animation with its own target Value and KeyTime. When the animation runs, it progresses from one key value to the next at the specified key times.

This example shows how to control the timing of key frames within a key-frame animation. Like other animations, key-frame animations have a Duration property. In addition to specifying the duration of an animation, you need to specify what part of that duration is allotted to each of its key frames. To allot the time, you specify a KeyTime for each key frame in the animation.

The KeyTime for each key frame specifies when a key frame ends (it does not specify the length of time a key frame plays). You can specify a KeyTime as a TimeSpan value; as a percentage; or as the Uniform or Paced special value.

The following example uses a DoubleAnimationUsingKeyFrames to animate a rectangle across the screen. The key frames' key times are set with TimeSpan values.

<!-- This Rectangle is animated with KeyTimes using TimeSpan Values.
It moves horizontally to 100 in the first 3 seconds, 100 to 300 in
the next second, and 300 to 500 in the last 6 seconds. --><RectangleFill="Blue"Stroke="Black"StrokeThickness="5"Width="50"Height="50"><Rectangle.RenderTransform><TranslateTransformx:Name="TranslateTransform1"/></Rectangle.RenderTransform><Rectangle.Triggers><EventTriggerRoutedEvent="Rectangle.Loaded"><BeginStoryboard><Storyboard><DoubleAnimationUsingKeyFramesStoryboard.TargetName="TranslateTransform1"Storyboard.TargetProperty="X"Duration="0:0:10"><!-- These KeyTime properties are specified as TimeSpan values
which are in the form of "hours:minutes:seconds". --><LinearDoubleKeyFrameValue="100"KeyTime="0:0:3"/><LinearDoubleKeyFrameValue="300"KeyTime="0:0:4"/><LinearDoubleKeyFrameValue="500"KeyTime="0:0:10"/></DoubleAnimationUsingKeyFrames></Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle>

The following illustration shows when the value of each key frame is reached.

The next example shows an animation that is identical, except that the key frames' key times are set with percentage values.

<!-- This rectangle moves horizontally to 100 in the first 3 seconds,
100 to 300 in the next second, and 300 to 500 in the last 6 seconds.--><RectangleFill="Purple"Stroke="Black"StrokeThickness="5"Width="50"Height="50"><Rectangle.RenderTransform><TranslateTransformx:Name="TranslateTransform2"/></Rectangle.RenderTransform><Rectangle.Triggers><EventTriggerRoutedEvent="Rectangle.Loaded"><BeginStoryboard><Storyboard><DoubleAnimationUsingKeyFramesStoryboard.TargetName="TranslateTransform2"Storyboard.TargetProperty="X"Duration="0:0:10"><!-- KeyTime properties are expressed as Percentages. --><LinearDoubleKeyFrameValue="100"KeyTime="30%"/><LinearDoubleKeyFrameValue="300"KeyTime="40%"/><LinearDoubleKeyFrameValue="500"KeyTime="100%"/></DoubleAnimationUsingKeyFrames></Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle>

The following illustration shows when the value of each key frame is reached.

/*
This rectangle is animated with KeyTimes using Uniform values.
Goes to 100 in the first 3.3 seconds, 100 to
300 in the next 3.3 seconds, 300 to 500 in the last 3.3 seconds.
*/// Create the a rectangle.
Rectangle aRectangle = new Rectangle();
aRectangle.Fill = Brushes.Red;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;
aRectangle.Width = 50;
aRectangle.Height = 50;
// Create a transform to move the rectangle// across the screen.
TranslateTransform translateTransform3 =
new TranslateTransform();
aRectangle.RenderTransform = translateTransform3;
// Create a DoubleAnimationUsingKeyFrames// to animate the transform.
DoubleAnimationUsingKeyFrames transformAnimation =
new DoubleAnimationUsingKeyFrames();
transformAnimation.Duration = TimeSpan.FromSeconds(10);
/*
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).
*/// Animate to 100.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(100, KeyTime.Uniform));
// Animate to 300.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(300, KeyTime.Uniform));
// Animate to 500.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(500, KeyTime.Uniform));
// Start the animation when the rectangle is loaded.
aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translateTransform3.BeginAnimation(TranslateTransform.XProperty, transformAnimation);
};

<!-- This rectangle is animated with KeyTimes using Uniform values.
Goes to 100 in the first 3.3 seconds, 100 to
300 in the next 3.3 seconds, 300 to 500 in the last 3.3 seconds. --><RectangleFill="Red"Stroke="Black"StrokeThickness="5"Width="50"Height="50"><Rectangle.RenderTransform><TranslateTransformx:Name="TranslateTransform3"/></Rectangle.RenderTransform><Rectangle.Triggers><EventTriggerRoutedEvent="Rectangle.Loaded"><BeginStoryboard><Storyboard><DoubleAnimationUsingKeyFramesStoryboard.TargetName="TranslateTransform3"Storyboard.TargetProperty="X"Duration="0:0:10"><!-- 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). --><LinearDoubleKeyFrameValue="100"KeyTime="Uniform"/><LinearDoubleKeyFrameValue="300"KeyTime="Uniform"/><LinearDoubleKeyFrameValue="500"KeyTime="Uniform"/></DoubleAnimationUsingKeyFrames></Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle>

The following illustration shows when the value of each key frame is reached.

/*
This rectangle is animated with KeyTimes using Paced Values.
The 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.
*/// Create the a rectangle.
Rectangle aRectangle = new Rectangle();
aRectangle.Fill = Brushes.Orange;
aRectangle.Stroke = Brushes.Black;
aRectangle.StrokeThickness = 5;
aRectangle.Width = 50;
aRectangle.Height = 50;
// Create a transform to move the rectangle// across the screen.
TranslateTransform translateTransform4 =
new TranslateTransform();
aRectangle.RenderTransform = translateTransform4;
// Create a DoubleAnimationUsingKeyFrames// to animate the transform.
DoubleAnimationUsingKeyFrames transformAnimation =
new DoubleAnimationUsingKeyFrames();
transformAnimation.Duration = TimeSpan.FromSeconds(10);
/*
Use Paced values 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.
*/// Animate to 100.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(100, KeyTime.Paced));
// Animate to 300.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(300, KeyTime.Paced));
// Animate to 500.
transformAnimation.KeyFrames.Add(
new LinearDoubleKeyFrame(500, KeyTime.Paced));
// Start the animation when the rectangle is loaded.
aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
{
translateTransform4.BeginAnimation(TranslateTransform.XProperty, transformAnimation);
};

<!-- This rectangle is animated with KeyTimes using Paced Values.
The 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. --><RectangleFill="Orange"Stroke="Black"StrokeThickness="5"Width="50"Height="50"><Rectangle.RenderTransform><TranslateTransformx:Name="TranslateTransform4"/></Rectangle.RenderTransform><Rectangle.Triggers><EventTriggerRoutedEvent="Rectangle.Loaded"><BeginStoryboard><Storyboard><DoubleAnimationUsingKeyFramesStoryboard.TargetName="TranslateTransform4"Storyboard.TargetProperty="X"Duration="0:0:10"><!-- Use Paced values 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. --><LinearDoubleKeyFrameValue="100"KeyTime="Paced"/><LinearDoubleKeyFrameValue="300"KeyTime="Paced"/><LinearDoubleKeyFrameValue="500"KeyTime="Paced"/></DoubleAnimationUsingKeyFrames></Storyboard></BeginStoryboard></EventTrigger></Rectangle.Triggers></Rectangle>

The following illustration shows when the value of each key frame is reached.

For simplicity, the code versions of this example use local animations, not storyboards, because only a single animation is being applied to a single property, but the examples may be modified to use storyboards instead. For an example showing how to declare a storyboard in code, see How to: Animate a Property by using a Storyboard.