Silverlight Animations (Part 1 - Basic Animation)

Creating animations is one of the main reasons for even being interested in Silverlight and so I'm going to put together a series of posts that go over Silverlight animations - from dead simple to sophisticated and cool. Along the way, I'll be constantly linking to places where you can get more detailed information but the content in these posts should be enough to get you started.

For more detailed info on Animations see Animation Overview

First, let's just walk through creating this simple animation (you have to click the rectangle to make it go): Fading Rectangle

Lazy Note: Actually, before I show you how to do this in code, let me remind you that you don't have to create animations in code at all! Yes, there are tools for doing this! Microsoft Blend 2 is a well funded tool (as opposed to something someone tossed together in their basement) that you ought to check out if you're going to do a lot of animations and design. At the time of writing this, there was a free trial version available. However, Blend 2 works by spitting out XAML so it doesn't hurt to learn the code way. Even using a tool, you might end up tweaking stuff by hand. Here's a QuickStart for using Blend 2 with animations. Finally, if you want to check out tools in general related to Silverlight - see here.

The example above uses a DoubleAnimation, which is a type of animation that generates Double values, to animate the Opacity property of a Rectangle. As a result, the Rectangle fades in and out of view. Here's the code for it.

    <StackPanel>
        <StackPanel.Resources>
            <!-- Animates the rectangle's opacity. -->
            <Storyboard x:Name="myStoryboard">
                <DoubleAnimation
                 Storyboard.TargetName="MyAnimatedRectangle"
                 Storyboard.TargetProperty="Opacity"
                 From="1.0" To="0.0" Duration="0:0:1"
                 AutoReverse="True"
                 RepeatBehavior="Forever" />
            </Storyboard>
        </StackPanel.Resources>

        <Rectangle MouseLeftButtonDown="Mouse_Clicked"
        x:Name="MyAnimatedRectangle"
        Width="100" Height="100" Fill="Blue" />

    </StackPanel>

And here is the C# code that begins the animation: 

        // When the user clicks the Rectangle, the animation
// begins.
public void Mouse_Clicked(object sender, MouseEventArgs e)
{
myStoryboard.Begin();
}

And again, here is the output of this code: Fading Rectangle 

Let's discuss the code above a bit. First, you have to to have an object who's property is going to get animated. In this sample, it's the rectangle:

<StackPanel>       
    <Rectangle MouseLeftButtonDown="Mouse_Clicked"
     x:Name="MyAnimatedRectangle"
     Width="100" Height="100" Fill="Blue" />
</StackPanel>

Notice that we've hooked an event to the rectangle (MouseLeftButtonDown) and we gave a name to the rectangle "MyAnimatedRectangle". The event is attached so that the user starts the animation when they click on the rectangle. The name is on there so that when we define the animation, we can target that rectangle to have its property animated.

Now we have to define the animation. An animation is defined inside of a Storyboard and it's convenient to put the Storyboard inside of a Resources block. In this example we use the StackPanel.Resources block so that the animation could be applied to any object in the parent StackPanel. Here's the code:

        <StackPanel.Resources>
            <!-- Animates the rectangle's opacity. -->
            <Storyboard x:Name="myStoryboard">
                <DoubleAnimation
                 Storyboard.TargetName="MyAnimatedRectangle"
                 Storyboard.TargetProperty="Opacity"
                 From="1.0" To="0.0" Duration="0:0:1"
                 AutoReverse="True"
                 RepeatBehavior="Forever" />
            </Storyboard>
        </StackPanel.Resources>

The Storyboard contains one or more animations (just one in this example). We give the Storyboard a name because we will want to refer to the Storyboard in the C# code by name to start the Storyboard - starting the Storyboard starts the animation.

Ok, the Storyboard contains a DoubleAnimation and it is this object that defines the actual animation. We're using a DoubleAnimation because the Opacity property that we're animating uses a Double for it's value. If you were animating a property that took a color you would use the ColorAnimation and if you were animating a property that used a Point, you would use the PointAnimation. There is also an ObjectAnimationUsingKeyFrames but I'll cover that in another post.

Note: DoubleAnimation is used more often than ColorAnimation or PointAnimation because more animatable properties use a double value versus a color or point. If you animate a property, more than likely it will be a DoubleAnimation or a DoubleAnimationUsingKeyFrames. No, I haven't covered key frame animations like DoubleAnimationUsingKeyFrames because those are a little more comlex. I will cover them in another post. For now, if you want to learn about keyframe animations (animations that create more realistic effects like acceleration/deceleration), check out the KeyFrame Animation Overview.

So as I said, in this example the DoubleAnimation defines the animation. It does this with a bunch of properties:

- Storyboard.TargetName (required): The name of the object who's property gets animated (the rectangle).
- Storyboard.TargetProperty (required): The property on the target object you want to animate (the Opacity property).
- From (optional): Specifies at what value the Opacity starts at. If you don't specify, the animation will start at whatever the properties current value is.
- To (optional): Specifies to what value the animation goes to. This is an optional property because you could use the By property instead.
- AutoReverse (optional): Whether the animation reverses back after completion. If you don't specify this, the default is false.
- RepeatBehanvior (optional): Whether the animation repeats itself and how often. If you don't specify this, the default is 1 time.

Finally, you have to start the animation. You do this in the C# handler for the MouseLeftButtonDown event. The Begin method starts the Storyboard:

        // When the user clicks the Rectangle, the animation
// begins.
public void Mouse_Clicked(object sender, MouseEventArgs e)
{
myStoryboard.Begin();
}

If you absolutely, positively don't want to use procedural code (e.g. C#, VB .NET, etc) to start a Storyboard, you can use Triggers in XAML but I'm not going to discuss Triggers here. The reason is that Triggers are really limited. They only work when you want the animation to start as soon as the object loads. Using events allows for this scenario (using the Loaded event) AND every other scenario that events allow (mouseover, keydown, etc).  

Ok, you made a simple animation and we went over the basic properties that define that animation and set it up. Now let me show you the other two animation objects used to create basic animations, namely ColorAnimation and PointAnimation. As you will see, all the same principles that apply to the DoubleAnimation example apply to ColorAnimation and PointAnimation.

Animating a Color

Run this sample.

<StackPanel Loaded="Start_Animation">
<StackPanel.Resources>
<Storyboard x:Name="colorStoryboard">

<!-- Animate the background color of the canvas from red to green
over 4 seconds. -->
<ColorAnimation BeginTime="00:00:00" Storyboard.TargetName="mySolidColorBrush"
Storyboard.TargetProperty="Color" From="Red" To="Green" Duration="0:0:4" />
</Storyboard>
</StackPanel.Resources>
<StackPanel.Background>
<SolidColorBrush x:Name="mySolidColorBrush" Color="Red" />
</StackPanel.Background>
</StackPanel>

// C#
// Start the animation when the object loads
public void Start_Animation(object sender, EventArgs e)
{
colorStoryboard.Begin();
}

Animating a Point

Run this sample.

    <Canvas Width="400" Height="300">
<Canvas.Resources>
<Storyboard x:Name="myStoryboard">

<!-- Animate the center point of the ellipse from 100 X, 300 Y
to 400 X, 100 Y over 5 seconds. -->
<PointAnimation
Storyboard.TargetProperty="Center"
Storyboard.TargetName="MyAnimatedEllipseGeometry"
Duration="0:0:5"
From="100,300"
To="400,100"
RepeatBehavior="Forever" />

</Storyboard>
</Canvas.Resources>
<Path Fill="Blue" Loaded="Start_Animation">
<Path.Data>

<!-- Describes an ellipse. -->
<EllipseGeometry x:Name="MyAnimatedEllipseGeometry"
Center="200,100" RadiusX="15" RadiusY="15" />
</Path.Data>
</Path>
</Canvas>

// C#
// Start the animation when the object loads
public void Start_Animation(object sender, EventArgs e)
{
myStoryboard.Begin();
}

In the next post, I'll talk about animating some other types of properties.

Sam Landstrom
Programmer Writer - Microsoft