Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / WPF

Advanced Animations in WPF

Rate me:
Please Sign up or sign in to vote.
5.00/5 (17 votes)
13 Apr 2013CPOL3 min read 85.8K   3.9K   43   12
This article describes advanced animations in WPF.

Image 1

Image 2

Image 3

Image 4

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.

  1. 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.
  2. Path animations allow you to define the path which an object follows, using PathGeometry. This is a more easier approach than keyframe animation.
  3. 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:

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

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:

Image 5

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:

Image 6 Image 7 Image 8

The following code uses SplineDoubleKeyFrame to produce smooth animation:

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

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:

Image 9

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.

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

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:

Image 10

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.

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

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 Image 11 using the following path geometry:

XML
<PathGeometry Figures="M 0,0 H45 M 35,-10 L 45,0,35,10"/>

and a path as follows:

Image 12

using the following path geometry:

XML
<PathGeometry Figures="M 100,200 C 100,25 400,350 400,175"/>

The DoesRotateWithTangent property is set to true to rotate the arrow along the path.

The following is the output of the above code:

Image 13

The following is the output of the above code if the DoesRotateWithTangent property is set to false:

Image 14

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Instructor / Trainer NIIT, India
India India
I am a trainer by profession. Currently I am working with iFuture Technologies(India) as a Senior Faculty. I enjoy programming as a hobby. During my career I have seen the growth and decline of many technologies, many of them being my favorites like Flash, WPF, Windows Mobile Development. Few of my current favorites are Android, Xamarin and Python, though I also like traditional and evergreen languages like PHP, C#, Visual Basic and Java.

Apart from computers, my favorite pastime is bicycling.

Comments and Discussions

 
Praisethx Pin
Burak Tunçbilek20-Jan-17 4:10
Burak Tunçbilek20-Jan-17 4:10 
QuestionAlternative for BitmapEffect Pin
Rupali Jadhav21-Nov-12 1:29
Rupali Jadhav21-Nov-12 1:29 
AnswerRe: Alternative for BitmapEffect Pin
Azim Zahir7-Dec-12 3:03
Azim Zahir7-Dec-12 3:03 
GeneralMy vote of 5 Pin
hari111r18-Nov-12 17:18
hari111r18-Nov-12 17:18 
Thank you so much Smile | :)
GeneralA five pointer Pin
nilotpalbarpujari20-Aug-12 14:42
nilotpalbarpujari20-Aug-12 14:42 
GeneralRe: A five pointer Pin
Azim Zahir24-Aug-12 3:54
Azim Zahir24-Aug-12 3:54 
GeneralMy vote of 5 Pin
RaghuramanKan10-May-12 8:00
RaghuramanKan10-May-12 8:00 
GeneralRe: My vote of 5 Pin
Azim Zahir11-May-12 6:30
Azim Zahir11-May-12 6:30 
GeneralVery Good Pin
Dave Kerr30-Apr-12 22:18
mentorDave Kerr30-Apr-12 22:18 
GeneralRe: Very Good Pin
Azim Zahir1-May-12 2:36
Azim Zahir1-May-12 2:36 
GeneralMy vote of 5 Pin
LaxmikantYadav30-Apr-12 19:52
LaxmikantYadav30-Apr-12 19:52 
GeneralRe: My vote of 5 Pin
Azim Zahir30-Apr-12 20:38
Azim Zahir30-Apr-12 20:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.