Click here to Skip to main content
Click here to Skip to main content

Advanced Animations in WPF

By , 13 Apr 2013
Rate this:
Please Sign up or sign in to vote.

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:

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

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>

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>

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>

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

and a path as follows:

using the following path geometry:

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

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.

License

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

About the Author

Azim Zahir
Instructor / Trainer NIIT, India
India India
I am a trainer by profession. Currently I am working with NIIT (Mumbai, India) as a Senior Faculty. I enjoy programming as a hobby. My favorite technologies are Flash, Flex and Silverlight.
 
Of late I have developed keen interest in WPF and Windows Mobile programming.
 
Apart from computers, my favorite pastime is bicycling.

Comments and Discussions

 
QuestionAlternative for BitmapEffect PinmemberRupali Jadhav21-Nov-12 1:29 
AnswerRe: Alternative for BitmapEffect PinmemberAzim Zahir7-Dec-12 3:03 
GeneralMy vote of 5 Pinmemberhari111r18-Nov-12 17:18 
GeneralA five pointer Pinmembernilotpalbarpujari20-Aug-12 14:42 
GeneralRe: A five pointer PinmemberAzim Zahir24-Aug-12 3:54 
GeneralMy vote of 5 PinmemberRaghuramanKan10-May-12 8:00 
GeneralRe: My vote of 5 PinmemberAzim Zahir11-May-12 6:30 
GeneralVery Good PinmvpDave Kerr30-Apr-12 22:18 
GeneralRe: Very Good PinmemberAzim Zahir1-May-12 2:36 
GeneralMy vote of 5 PinmemberLaxmikant_Yadav30-Apr-12 19:52 
GeneralRe: My vote of 5 PinmemberAzim Zahir30-Apr-12 20:38 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 13 Apr 2013
Article Copyright 2012 by Azim Zahir
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid