Introduction
This article is a continuation of my previous article Animation using Storyboards in WPF.
In that article, I had written about Double Animation and Color Animation. In this article, I am describing KeyFrame Animation, Path Animation, and Matrix Animation.
Double Animation and Color Animation are simple animations which have a starting point and ending point. As such, it is difficult to use them for more complex animations.
We can use KeyFrame Animation, Path Animation, and Matrix Animation to have more control over complex animations.
- Keyframe animations are based on keyframes which define the important points of an animation. In-between frames are drawn later. WPF automatically generates the in-between frames.
- Path animations allow you to define the path which an object follows, using
PathGeometry
. This is a more easier approach than keyframe animation.
- Matrix animation is a special type of path animation. Matrix animation can be used to control the position and orientation of an object.
Background
Linear KeyFrame Animation
The following code animates an ellipse using a linear keyframe animation:
<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>Colourised in 31ms
In the above code, a simple DoubleAnimation
is used to control the horizontal movement of the ellipse from 0 to 400 in a duration of 5 seconds.
The DoubleAnimationUsingKeyFrames
element controls the vertical movement of the ellipse. It specifies 5 keyframes at intervals of 0.5 seconds.
The LinearDoubleKeyFrame
element is used to specify the keyframes. LinearDoubleKeyFrame
does not produce a smooth animation because
the change in value between two frames is constant.
Following is the output of the above code:
Spline KeyFrame Animation
To create a smooth animation, we can use SplineDoubleKeyFrame
.
SplineDoubleKeyFrame
uses a mathematical function to calculate how the object should accelerate or decelerate. The
KeySpline
attribute can be used to specify this value.
The following figures illustrate this:
The following code uses SplineDoubleKeyFrame
to produce smooth animation:
<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>Colourised in 37ms
The above code produces a more realistic animation by causing the animation to accelerate gradually after starting slowly.
The following is the output of the above code:
Path Animation
Path animation can be used to move an object on a canvas by changing its position. This can be done by setting the
Canvas.Left
and Canvas.Top
properties. Since these properties are of type
double
, we can use DoubleAnimationUsingPath
to animate the object.
Following is the code which uses a path animation to move an ellipse on an elliptical path.
<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>Colourised in 10ms
The above code creates a PathGeometry
object as a canvas resource. Then it uses the PathGeometry
attribute of DoubleAnimationUsingPath
to change the position of the ellipse on the path. To understand the syntax of PathGeometry
, refer to the following
link: http://msdn.microsoft.com/en-us/library/ms752293.aspx.
Following is the output of the above code:
Matrix Animation
Matrix animation can be used to control an object's position and orientation. We can control the rotation of the object on a path using
the DoesRotateWithTangent
property.
I have used the following code to move an arrow on a path.
<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>Colourised in 53ms
The above code uses a MatrixAnimationUsingPath
to move an arrow along a path defined using a
PathGeometry
and ColorAnimation
to change the color of the arrow as it moves. I have created an arrow as follows
using the following path geometry:
<PathGeometry Figures="M 0,0 H45 M 35,-10 L 45,0,35,10"/>Colourised in 1ms
and a path as follows:
using the following path geometry:
<PathGeometry Figures="M 100,200 C 100,25 400,350 400,175"/>Colourised in 0ms
The DoesRotateWithTangent
property is set to true to rotate the arrow along the path.
The following is the output of the above code:
The following is the output of the above code if the DoesRotateWithTangent
property is set to false
:
Using the code
I have created an application which demonstrates all the above animations using a tabbed interface.
Points of interest
I have used Visual C# 2010 Express Edition to do all the coding. I hope that readers find this article helpful in understanding the various aspects of animation in WPF.