Click here to Skip to main content
15,860,859 members
Articles / Desktop Programming / WPF

Animation using Storyboards in WPF

Rate me:
Please Sign up or sign in to vote.
4.90/5 (58 votes)
13 Apr 2013CPOL3 min read 305.2K   11.2K   67   48
Animation using Storyboards in WPF.

Image 1

Introduction

Animation in WPF has been made easier because WPF achieves animation by modifying properties of elements, whereas in Windows Forms, a developer has to create a timer and modify the appearance of elements on the tick event of a timer. WPF uses its own timing system which can be written using managed code and XAML. The internal work of redrawing the screen is handled efficiently by WPF. While animating using WPF, you just need to focus on the effects you want to create without bothering about how to achieve those effects.

To demonstrate this, I have created a Waving Flag animation which uses a series of images displayed in a sequence.

Background

DoubleAnimation

WPF achieves animation by animating element properties. For example, if you want to produce a zoom in or zoom out effect for a rectangle, you can animate the width and height properties. The following code animates a rectangle by modifying its width and height properties.

XML
<Rectangle Name="myrect" Width="1" Height="1">
    <Rectangle.Fill>
        <SolidColorBrush Color="Red"/>
    </Rectangle.Fill>   
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard RepeatBehavior="Forever">
                    <DoubleAnimation Storyboard.TargetName="myrect" 
                       Storyboard.TargetProperty="Width" From="1" To="350" 
                       Duration="0:0:1" BeginTime="0:0:0"/>
                    <DoubleAnimation Storyboard.TargetName="myrect" 
                       Storyboard.TargetProperty="Height" From="1" To="250" 
                       Duration="0:0:1" BeginTime="0:0:1"/>
                    <DoubleAnimation Storyboard.TargetName="myrect" 
                       Storyboard.TargetProperty="Height" From="250" 
                       To="1" Duration="0:0:1" BeginTime="0:0:2"/>
                    <DoubleAnimation Storyboard.TargetName="myrect" 
                       Storyboard.TargetProperty="Width" From="350" To="1" 
                       Duration="0:0:1" BeginTime="0:0:3"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

This code triggers the animation automatically when the window is loaded. The code adds an EventTrigger to the rectangle. The BeginStoryboard action runs a storyboard. This storyboard uses four DoubleAnimations. The first DoubleAnimation increases the width of the rectangle from 1 to 350. The second one increases the height from 1 to 250. The third and fourth do the reverse by decreasing the height and width back to 1. The four DoubleAnimations are made to run in a sequence by setting the BeginTime attribute such that each animation starts when the previous is over. The RepeatBehavior attribute of the Storyboard is assigned the value "Forever" which makes the animation run indefinitely.

Following is the output of the above code:

Image 2

Controlling the Animation from Code-Behind

The animation can be controlled from the code-behind by creating a storyboard as a window resource and locating it in code by using the TryFindResource method as follows:

C#
Storyboard s = (Storyboard)TryFindResource("sb");

Following is the code to create the Storyboard resource:

XML
<Window.Resources>
    <Storyboard x:Key="sb" RepeatBehavior="Forever">
        <DoubleAnimation Storyboard.TargetName="myrect" 
          Storyboard.TargetProperty="Width" From="1" To="350" 
          Duration="0:0:1" BeginTime="0:0:0"/>
        <DoubleAnimation Storyboard.TargetName="myrect" 
          Storyboard.TargetProperty="Height" From="1" To="250" 
          Duration="0:0:1" BeginTime="0:0:1"/>
        <DoubleAnimation Storyboard.TargetName="myrect" 
          Storyboard.TargetProperty="Height" From="250" To="1" 
          Duration="0:0:1" BeginTime="0:0:2"/>
        <DoubleAnimation Storyboard.TargetName="myrect" 
          Storyboard.TargetProperty="Width" From="350" To="1" 
          Duration="0:0:1" BeginTime="0:0:3"/>
    </Storyboard>
</Window.Resources>

The following is the code to control the animation programmatically:

C#
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void btnStart_Click(object sender, RoutedEventArgs e)
    {
        // Locate Storyboard resource
        Storyboard s = (Storyboard)TryFindResource("sb");
        s.Begin();	// Start animation
    }

    private void btnStop_Click(object sender, RoutedEventArgs e)
    {
        Storyboard s = (Storyboard)TryFindResource("sb");
        s.Stop();	// Stop animation
    }

    private void btnPause_Click(object sender, RoutedEventArgs e)
    {
        Storyboard s = (Storyboard)TryFindResource("sb");
        s.Pause();	// Pause animation
    }

    private void btnResume_Click(object sender, RoutedEventArgs e)
    {
        Storyboard s = (Storyboard)TryFindResource("sb");
        s.Resume();	// Resume animation
    }
}

Following is the output of the above code:

Image 3

Fade In and Fade Out Animation Using DoubleAnimation

Fade In and Fade Out Animation effects can be created using the Opacity property as follows:

XML
<Rectangle Name="myrect" Width="350" Height="250">
    <Rectangle.Fill>
        <SolidColorBrush x:Name="brush" Color="Red"/>
    </Rectangle.Fill>
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="myrect" 
                        Storyboard.TargetProperty="Opacity" From="0" To="1" 
                        Duration="0:0:1" BeginTime="0:0:0" AutoReverse="True" 
                        RepeatBehavior="Forever"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

The above code changes the opacity of the rectangle from 0 (completely transparent) to 1 (completely opaque).

The output of the above code is as follows:

Image 4

ColorAnimation

We can use ColorAnimation to animate the Color property of a rectangle. Following is the code to produce color animation:

XML
<Rectangle Name="myrect" Width="350" Height="250">
    <Rectangle.Fill>
        <SolidColorBrush x:Name="brush" Color="Red"/>
    </Rectangle.Fill>
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard RepeatBehavior="Forever">
                    <ColorAnimation Storyboard.TargetName="brush" 
                      Storyboard.TargetProperty="Color" From="Red" To="Green" 
                      Duration="0:0:1" BeginTime="0:0:0"/>
                    <ColorAnimation Storyboard.TargetName="brush" 
                      Storyboard.TargetProperty="Color" From="Green" To="Blue" 
                      Duration="0:0:1" BeginTime="0:0:1"/>
                    <ColorAnimation Storyboard.TargetName="brush" 
                      Storyboard.TargetProperty="Color" From="Blue" To="Yellow" 
                      Duration="0:0:1" BeginTime="0:0:2"/>
                    <ColorAnimation Storyboard.TargetName="brush" 
                      Storyboard.TargetProperty="Color" From="Yellow" 
                      To="Red" Duration="0:0:1" BeginTime="0:0:3"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

This code uses four ColorAnimations to change the color of the rectangle. The timing of the color change is controlled by using the BeginTime property.

The above code produces the following output:

Image 5

Animating Gradient Using ColorAnimation

ColorAnimation can also be used to create gradient animation. The following code can be used for this:

XML
<Rectangle Name="myrect" Width="350" Height="250">
    <Rectangle.Fill>
        <LinearGradientBrush x:Name="brush" StartPoint="0,0" EndPoint="1,1">
            <GradientStop x:Name="stop1" Offset="0" Color="Red"/>
            <GradientStop x:Name="stop2" Offset="0.5" Color="Green"/>
            <GradientStop x:Name="stop3" Offset="1" Color="Blue"/>
        </LinearGradientBrush>
    </Rectangle.Fill>
    <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Window.Loaded">
            <BeginStoryboard>
                <Storyboard RepeatBehavior="Forever">
                    <ColorAnimation Storyboard.TargetName="stop1" Storyboard.TargetProperty="Color" 
                       From="Red" To="Green" Duration="0:0:1" BeginTime="0:0:0"/>
                    <ColorAnimation Storyboard.TargetName="stop1" Storyboard.TargetProperty="Color" 
                       From="Green" To="Blue" Duration="0:0:1" BeginTime="0:0:0.5"/>
                    <ColorAnimation Storyboard.TargetName="stop1" Storyboard.TargetProperty="Color" 
                       From="Blue" To="Red" Duration="0:0:1" BeginTime="0:0:1"/>
                    <ColorAnimation Storyboard.TargetName="stop2" Storyboard.TargetProperty="Color" 
                       From="Green" To="Blue" Duration="0:0:1" BeginTime="0:0:0"/>
                    <ColorAnimation Storyboard.TargetName="stop2" Storyboard.TargetProperty="Color" 
                       From="Blue" To="Red" Duration="0:0:1" BeginTime="0:0:0.5"/>
                    <ColorAnimation Storyboard.TargetName="stop2" Storyboard.TargetProperty="Color" 
                       From="Red" To="Green" Duration="0:0:1" BeginTime="0:0:1"/>
                    <ColorAnimation Storyboard.TargetName="stop3" Storyboard.TargetProperty="Color" 
                       From="Blue" To="Red" Duration="0:0:1" BeginTime="0:0:0"/>
                    <ColorAnimation Storyboard.TargetName="stop3" Storyboard.TargetProperty="Color" 
                       From="Red" To="Green" Duration="0:0:1" BeginTime="0:0:0.5"/>
                    <ColorAnimation Storyboard.TargetName="stop3" Storyboard.TargetProperty="Color" 
                       From="Green" To="Blue" Duration="0:0:1" BeginTime="0:0:1"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Rectangle.Triggers>
</Rectangle>

The above code initially creates a rectangle having a linear gradient of Red, Green, and Blue colors. Then it animates each gradient to change its color.

Following is the output of the above code:

Image 6

Using the Code

I have created an application which displays an animated Indian flag. The full XAML code of the application is as follows:

XML
<Window x:Class="AnimatedFlag.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Indian Flag" Height="350" Width="525">
    <Grid>
        <Image Name="flagImage" Margin="12">
            <Image.Triggers>
                <EventTrigger RoutedEvent="Window.Loaded">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Name="da" Storyboard.TargetName="flagImage" 
                               Storyboard.TargetProperty="Width" From="200" To="200" 
                               Duration="0:0:0.1" Completed="DoubleAnimation_Completed"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Image.Triggers>
        </Image>
    </Grid>
</Window>

This code creates a dummy animation. I call it dummy animation because it does not actually change any property. The <DoubleAnimation> element just uses the Width property of the image but the values of the From and To attributes are the same (200). The Duration attribute specifies the animation duration as 0.1 second. It uses the Completed event handler to restart the animation after it is completed. The code-behind code is as follows:

C#
public partial class MainWindow : Window
{
    int ctr = 1;
    public MainWindow()
    {
        InitializeComponent();
    }

    private void DoubleAnimation_Completed(object sender, EventArgs e)
    {
        ShowImage();	// Display Image
        da.BeginAnimation(Image.WidthProperty, da);	// Start Animation
    }

    private void ShowImage()
    {
        string filename = "Images/Flag" + ctr + ".jpg";
        BitmapImage image = new BitmapImage();
        image.BeginInit();
        image.UriSource = new Uri(filename, UriKind.Relative);
        image.EndInit();
        flagImage.Source = image;
        ctr++;
        if (ctr > 6)
        {
            ctr = 1;	// Display first image after the last image
        }
    }
}

In the above code, the DoubleAnimation_Completed event handler calls the ShowImage() function to display six images in a sequence. It uses the BeginAnimation() method of the DoubleAnimation class to restart the animation. The first parameter of the BeginAnimation method is Image.WidthProperty which is a DependencyProperty. The second parameter is the AnimationTimeline object.

The output of the program is as follows:

Image 7

Points of Interest

I have created this application using Microsoft Visual C# 2010 Express Edition. I hope that this article will help in understanding the concepts of Storyboard and Animations 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

 
QuestionWPF gif loader Pin
Pawar.Nilesh20-May-19 2:33
professionalPawar.Nilesh20-May-19 2:33 
PraiseVote of 5 Pin
Beginner Luck2-Feb-16 16:00
professionalBeginner Luck2-Feb-16 16:00 
QuestionShow multiple images as a random moves and select any one after timer elapses Pin
Member 100640607-Mar-15 19:16
Member 100640607-Mar-15 19:16 
GeneralMy vote of 3 Pin
jefffhaynes3-Jul-14 13:13
jefffhaynes3-Jul-14 13:13 
QuestionBetter way for animations Pin
Edgar130129-Sep-13 0:59
Edgar130129-Sep-13 0:59 
AnswerRe: Better way for animations Pin
Azim Zahir30-Sep-13 18:26
Azim Zahir30-Sep-13 18:26 
QuestionApplying same wave effect to a static "wave" image Pin
Member 293896111-Jun-13 13:03
Member 293896111-Jun-13 13:03 
AnswerRe: Applying same wave effect to a static "wave" image Pin
Azim Zahir11-Jun-13 23:16
Azim Zahir11-Jun-13 23:16 
GeneralMy vote of 5 Pin
SagarRS18-May-13 20:58
professionalSagarRS18-May-13 20:58 
QuestionGreat, clear, useful article :-) Pin
causg29-Apr-13 4:40
causg29-Apr-13 4:40 
AnswerRe: Great, clear, useful article :-) Pin
Azim Zahir29-Apr-13 16:41
Azim Zahir29-Apr-13 16:41 
GeneralMy vote of 5 Pin
loulou_7501614-Mar-13 10:00
loulou_7501614-Mar-13 10:00 
GeneralRe: My vote of 5 Pin
Azim Zahir17-Mar-13 0:18
Azim Zahir17-Mar-13 0:18 
GeneralMy vote of 5 Pin
SalCon7-Mar-13 4:05
SalCon7-Mar-13 4:05 
GeneralRe: My vote of 5 Pin
Azim Zahir11-Mar-13 19:12
Azim Zahir11-Mar-13 19:12 
GeneralMy vote of 5 Pin
CzimerA17-Jan-13 0:23
CzimerA17-Jan-13 0:23 
GeneralRe: My vote of 5 Pin
Azim Zahir18-Jan-13 15:37
Azim Zahir18-Jan-13 15:37 
QuestionWhat's wrong with following code? Pin
mohammed190.sobhy4-Dec-12 17:33
mohammed190.sobhy4-Dec-12 17:33 
AnswerRe: What's wrong with following code? Pin
Azim Zahir7-Dec-12 2:45
Azim Zahir7-Dec-12 2:45 
GeneralMy vote of 5 Pin
mohammed190.sobhy4-Dec-12 17:22
mohammed190.sobhy4-Dec-12 17:22 
GeneralMy vote of 5 Pin
hari111r18-Nov-12 17:11
hari111r18-Nov-12 17:11 
GeneralMy vote of 5 Pin
k.shekhar117-Sep-12 21:13
k.shekhar117-Sep-12 21:13 
GeneralRe: My vote of 5 Pin
Azim Zahir19-Sep-12 18:01
Azim Zahir19-Sep-12 18:01 
Questionhello Pin
chilman17-Aug-12 21:09
chilman17-Aug-12 21:09 
AnswerRe: hello Pin
Azim Zahir24-Aug-12 4:07
Azim Zahir24-Aug-12 4:07 

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.