Sdílet prostřednictvím


Animation Overview

Microsoft Silverlight will reach end of support after October 2021. Learn more.

In Silverlight, animation can enhance your graphical creation by adding movement and interactivity. By animating a background color or applying an animated Transform, you can create dramatic screen transitions or provide helpful visual cues.

This topic contains the following sections.

  • Introducing Animations
  • Making a UIElement Fade In and Out of View
  • Start, Stop, Pause, and Resume an Animation
  • Controlling the Begin Time of Animations
  • Creating an Animation in Procedural Code
  • Animation Types
  • Applying an Animation to a Property
  • Animating Transforms
  • What Happens After an Animation Ends
  • Easing Functions
  • Custom Animations
  • Related Topics

Introducing Animations

Animation is an illusion that is created by quickly cycling through a series of images, each slightly different from the last. The brain perceives the group of images as a single changing scene. In film, this illusion is created by using cameras that record many photographs, or frames, each second. When the frames are played back by a projector, the audience sees a moving picture. In Silverlight, you animate objects by applying animation to their individual properties. For example, to make a UIElement grow, you animate its Width and Height properties. To make a UIElement fade from view, you animate its Opacity property. Silverlight contains many objects that have properties that can be animated.

NoteNote:

In Silverlight, you can perform simple animations only on properties whose values are of type Double, Color, or Point. In addition, you can animate properties of other types by using ObjectAnimationUsingKeyFrames, but this is done using discrete interpolation (jumping from one value to another), which is not what most people consider to be true animation.

The next section shows how to create a simple animation that makes a Rectangle, a type of UIElement, fade in and out of view.

Making a UIElement Fade In and Out of View

This example shows how to use a Silverlight animation to make a Rectangle fade in and out of view by animating a property value. It 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. To see a preview of the animation you will be walked through, click the link below to run the sample and then click on the rectangle to begin the animation.

Run this sample

The first part of the example creates a Rectangle element and displays it in a StackPanel.

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

To create an animation and apply it to the rectangle's Opacity property, you do the following:

These steps are discussed in detail in the following sections. For the full example, see the Complete Example section.

Creating a DoubleAnimation

Because the Opacity property is of type Double, you need an animation that produces Double values. A DoubleAnimation is one such animation; it creates a transition between two Double values. To specify the starting value of the DoubleAnimation, you set its From property. To specify its ending value, you set its To property.

  1. An opacity value of 1.0 makes the object completely opaque, and an opacity value of 0.0 makes it completely invisible. To make the animation transition from 1.0 to 0.0, you set its From property to 1.0 and its To property to 0.0.

    <DoubleAnimation From="1.0" To="0.0"  />
    
  2. Specify a Duration for the animation. The Duration property of an animation specifies how long it takes to go from its starting value to its destination value. The following example sets the duration of the animation to one second.

    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:1" />
    
  3. The preceding example creates an animation that transitions from 1.0 to 0.0, which causes the target element to fade from completely opaque to completely invisible. To make the element fade back into view after it vanishes, set the AutoReverse property to true. To make the animation repeat indefinitely, set its RepeatBehavior property to Forever.

    <DoubleAnimation From="1.0" To="0.0" Duration="0:0:1" 
      AutoReverse="True" RepeatBehavior="Forever"/>
    

Creating a Storyboard

To apply an animation to an object, you create a Storyboard object and use the TargetName and TargetProperty attached properties to specify the object and property to animate.

  1. Create the Storyboard and add the animation as its child.

    <Storyboard>
      <DoubleAnimation From="1.0" To="0.0" Duration="0:0:1" 
        AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

    Although the Storyboard in this example contains only a single animation, you may add multiple animations.

  2. Use the TargetName attached property to specify the object to animate. In the following code, the DoubleAnimation is given a target name of myAnimatedRectangle, which is the name of the object to animate.

    <Storyboard>
      <DoubleAnimation
        Storyboard.TargetName="MyAnimatedRectangle"
        From="1.0" To="0.0" Duration="0:0:1" 
        AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    
  3. Use the TargetProperty attached property to specify the property to animate. In the following code, the animation is configured to target the Opacity property of a Rectangle.

    <Storyboard>
      <DoubleAnimation
        Storyboard.TargetName="MyAnimatedRectangle" 
        Storyboard.TargetProperty="Opacity"
        From="1.0" To="0.0" Duration="0:0:1" 
        AutoReverse="True" RepeatBehavior="Forever" />
    </Storyboard>
    

Associating the Storyboard with an Event

At this point you have specified the target object of the animation and how the animation behaves; now you need to specify when the animation begins. You can do this by using an event.

1. Make the Storyboard a Resource. Place the Storyboard inside a resource block so that you can easily reference the Storyboard from code to start, stop, pause, and resume. The following markup shows the Storyboard declared in the StackPanel object resources block. Note that you can declare the Storyboard in any resources block that is within the same scope as the object you wish to animate.

<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
    x:Name="MyAnimatedRectangle"
    Width="100" Height="100" Fill="Blue" />

</StackPanel>

2. Attach an Event to an Element. There are a variety of events you can use to start an animation, including mouse-related events such as MouseLeftButtonDown, which is raised when a user clicks an object, or the Loaded event, which is raised when an object first loads. For more information about events, see Events Overview for Silverlight. In this example, the MouseLeftButtonDown event is attached to the Rectangle so that when the user clicks the rectangle, the event is raised.

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

3. Control the Animation from the Event Handler.Storyboard has several methods that allow you to control the playback of the Storyboard animation, including Begin, Stop, Pause, and Resume. In this example, the Begin method is used to start the animation when the user clicks the rectangle and raises the MouseLeftButtonDown event.

' When the user clicks the Rectangle, the animation
' begins.
Private Sub Mouse_Clicked(ByVal sender As Object, ByVal e As MouseEventArgs)
    myStoryboard.Begin()
End Sub
// When the user clicks the Rectangle, the animation
// begins.
private void Mouse_Clicked(object sender, MouseEventArgs e)
{
    myStoryboard.Begin();
}

Complete Example

The following example shows the complete XAML markup for creating a rectangle that fades in and out of view when it is loaded.

Run this sample

  <UserControl x:Class="animation_ovw_intro.Page"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
  Width="400" Height="300">

  <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>
    <TextBlock Margin="10">Click on the rectangle to start the animation.</TextBlock>

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

  </StackPanel>
</UserControl>
' When the user clicks the Rectangle, the animation
' begins.
Private Sub Mouse_Clicked(ByVal sender As Object, ByVal e As MouseEventArgs)
    myStoryboard.Begin()
End Sub
// When the user clicks the Rectangle, the animation
// begins.
private void Mouse_Clicked(object sender, MouseEventArgs e)
{
    myStoryboard.Begin();
}

Start, Stop, Pause, and Resume an Animation

The previous example showed how to start an animation using the Begin method; however, Storyboard also has the Stop, Pause, and Resume methods that can be used to control an animation. The following example presents a series of buttons that allow the user to control the animation of an Ellipse across the screen.

Run this sample

<UserControl x:Class="interactive_animation.Page"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
  Width="400" Height="300">
    <StackPanel>
        <TextBlock Margin="10" TextWrapping="Wrap">This sample uses the Begin, Pause, Resume, and Stop methods to control an animation.</TextBlock>
        <Canvas>
            <Canvas.Resources>
                <Storyboard x:Name="myStoryboard">

                    <!-- Animate the center point of the ellipse. -->
                    <PointAnimation Storyboard.TargetProperty="Center"
          Storyboard.TargetName="MyAnimatedEllipseGeometry"
          Duration="0:0:5"
          From="20,200"
          To="400,100"
          RepeatBehavior="Forever" />
                </Storyboard>
            </Canvas.Resources>

            <Path Fill="Blue">
                <Path.Data>
                    <!-- Describes an ellipse. -->
                    <EllipseGeometry x:Name="MyAnimatedEllipseGeometry"
          Center="20,20" RadiusX="15" RadiusY="15" />
                </Path.Data>
            </Path>

            <StackPanel Orientation="Horizontal" Canvas.Left="10" Canvas.Top="265">
                <!-- Button that begins animation. -->
                <Button Click="Animation_Begin"
        Width="65" Height="30" Margin="2" Content="Begin" />

                <!-- Button that pauses Animation. -->
                <Button Click="Animation_Pause"
        Width="65" Height="30" Margin="2" Content="Pause" />

                <!-- Button that resumes Animation. -->
                <Button Click="Animation_Resume"
        Width="65" Height="30" Margin="2" Content="Resume" />

                <!-- Button that stops Animation. Stopping the animation returns the
        ellipse to its original location. -->
                <Button Click="Animation_Stop"
        Width="65" Height="30" Margin="2" Content="Stop" />
            </StackPanel>

        </Canvas>
    </StackPanel>
</UserControl>
Private Sub Animation_Begin(ByVal sender As Object, ByVal e As RoutedEventArgs)
    myStoryboard.Begin()
End Sub

Private Sub Animation_Pause(ByVal sender As Object, ByVal e As RoutedEventArgs)
    myStoryboard.Pause()
End Sub

Private Sub Animation_Resume(ByVal sender As Object, ByVal e As RoutedEventArgs)
    myStoryboard.Resume()
End Sub

Private Sub Animation_Stop(ByVal sender As Object, ByVal e As RoutedEventArgs)
    myStoryboard.Stop()
End Sub
private void Animation_Begin(object sender, RoutedEventArgs e)
{
    myStoryboard.Begin();
}
private void Animation_Pause(object sender, RoutedEventArgs e)
{
    myStoryboard.Pause();
}
private void Animation_Resume(object sender, RoutedEventArgs e)
{
    myStoryboard.Resume();
}
private void Animation_Stop(object sender, RoutedEventArgs e)
{
    myStoryboard.Stop();
}

Controlling the Begin Time of Animations

Storyboard as well as all the other animation objects (DoubleAnimation, DoubleAnimationUsingKeyFrames, ColorAnimation, and so on) inherit from the Timeline class (see Animations Are Timelines later in this topic). The Timeline class confers many useful properties to these animation objects including the BeginTime property. As the name suggests, the BeginTime property allows you to specify a time at which point the animation object begins activity. For example, you could specify a time of two seconds on the BeginTime of a Storyboard. When you begin the Storyboard using the Begin method, the Storyboard will wait two seconds and then begin. In addition you can specify BeginTime on the animation objects inside of the Storyboard. For example, if you have a Storyboard with a two-second BeginTime and this Storyboard contains two DoubleAnimation objects -- one with no BeginTime specified and the other with a BeginTime of three -- the first DoubleAnimation will start two seconds after the Begin method is called on the Storyboard and the second DoubleAnimation will begin five seconds afterward (two seconds delay for the Storyboard plus three seconds delay for the DoubleAnimation). The following example shows this.

Run this sample

<StackPanel>
    <StackPanel.Resources>

        <!-- Storyboard starts 2 seconds after its Begin
             method is called. -->
        <Storyboard BeginTime="0:0:2" x:Name="myStoryboard">

            <!-- Animates the rectangle's width. No 
                 BeginTime specified so by default begins 
                 as soon as it's parent (the Storyboard)
                 begins. -->
            <DoubleAnimation 
              Storyboard.TargetName="MyAnimatedRectangle" 
              Storyboard.TargetProperty="Width"
              To="300" Duration="0:0:1" />

            <!-- Animates the rectangle's opacity. A BeginTime
                 of 3 seconds specified so begins three seconds
                 after the Storyboard begins (total of 5 seconds)-->
            <DoubleAnimation BeginTime="0:0:3"
              Storyboard.TargetName="MyAnimatedRectangle" 
              Storyboard.TargetProperty="Opacity"
              To="0" Duration="0:0:1" />
        </Storyboard>
    </StackPanel.Resources>

    <Rectangle x:Name="MyAnimatedRectangle" 
               Loaded="Start_Animation"
               Width="100" Height="100" Fill="Blue" />

</StackPanel>
        </StackPanel>
' Start the animation when the object loads.
Private Sub Start_Animation(ByVal sender As Object, ByVal e As EventArgs)
    myStoryboard.Begin()
End Sub
// Start the animation when the object loads.
private void Start_Animation(object sender, EventArgs e)
{
    myStoryboard.Begin();
}

You can think of a Storyboard as a container for other animation objects (for example, DoubleAnimation) as well as other Storyboard objects. That is, you can nest Storyboard objects within each other and specify BeginTime values for each Storyboard separately. Using nested Storyboards can help you orchestrate elaborate animation sequences. Each child Storyboard will wait until its parent Storyboard begins and then start the countdown before it in turn begins.

Creating an Animation in Procedural Code

Rather than using XAML, you can also create an animation completely in procedural code (such as C# or Visual Basic). The following example shows how to create an animation that animates the Canvas.Top and Canvas.Left attached properties of a Rectangle.

Run this sample

Private Sub Create_And_Run_Animation(ByVal sender As Object, ByVal e As EventArgs)
    ' Create a red rectangle that will be the target
    ' of the animation.
    Dim myRectangle As Rectangle = New Rectangle
    myRectangle.Width = 200
    myRectangle.Height = 200
    Dim myColor As Color = Color.FromArgb(255, 255, 0, 0)
    Dim myBrush As SolidColorBrush = New SolidColorBrush
    myBrush.Color = myColor
    myRectangle.Fill = myBrush
    ' Add the rectangle to the tree.
    LayoutRoot.Children.Add(myRectangle)
    ' Create a duration of 2 seconds.
    Dim duration As Duration = New Duration(TimeSpan.FromSeconds(2))
    ' Create two DoubleAnimations and set their properties.
    Dim myDoubleAnimation1 As DoubleAnimation = New DoubleAnimation
    Dim myDoubleAnimation2 As DoubleAnimation = New DoubleAnimation
    myDoubleAnimation1.Duration = duration
    myDoubleAnimation2.Duration = duration
    Dim sb As Storyboard = New Storyboard
    sb.Duration = duration
    sb.Children.Add(myDoubleAnimation1)
    sb.Children.Add(myDoubleAnimation2)
    Storyboard.SetTarget(myDoubleAnimation1, myRectangle)
    Storyboard.SetTarget(myDoubleAnimation2, myRectangle)
    ' Set the attached properties of Canvas.Left and Canvas.Top
    ' to be the target properties of the two respective DoubleAnimations
    Storyboard.SetTargetProperty(myDoubleAnimation1, New PropertyPath("(Canvas.Left)"))
    Storyboard.SetTargetProperty(myDoubleAnimation2, New PropertyPath("(Canvas.Top)"))
    myDoubleAnimation1.To = 200
    myDoubleAnimation2.To = 200
    ' Make the Storyboard a resource.
    LayoutRoot.Resources.Add("unique_id", sb)
    ' Begin the animation.
    sb.Begin()
End Sub
private void Create_And_Run_Animation(object sender, EventArgs e)
{
    // Create a red rectangle that will be the target
    // of the animation.
    Rectangle myRectangle = new Rectangle();
    myRectangle.Width = 200;
    myRectangle.Height = 200;
    Color myColor = Color.FromArgb(255, 255, 0, 0);
    SolidColorBrush myBrush = new SolidColorBrush();
    myBrush.Color = myColor;
    myRectangle.Fill = myBrush;

    // Add the rectangle to the tree.
    LayoutRoot.Children.Add(myRectangle);

    // Create a duration of 2 seconds.
    Duration duration = new Duration(TimeSpan.FromSeconds(2));

    // Create two DoubleAnimations and set their properties.
    DoubleAnimation myDoubleAnimation1 = new DoubleAnimation();
    DoubleAnimation myDoubleAnimation2 = new DoubleAnimation();

    myDoubleAnimation1.Duration = duration;
    myDoubleAnimation2.Duration = duration;

    Storyboard sb = new Storyboard();
    sb.Duration = duration;

    sb.Children.Add(myDoubleAnimation1);
    sb.Children.Add(myDoubleAnimation2);

    Storyboard.SetTarget(myDoubleAnimation1, myRectangle);
    Storyboard.SetTarget(myDoubleAnimation2, myRectangle);

    // Set the attached properties of Canvas.Left and Canvas.Top
    // to be the target properties of the two respective DoubleAnimations.
    Storyboard.SetTargetProperty(myDoubleAnimation1, new PropertyPath("(Canvas.Left)"));
    Storyboard.SetTargetProperty(myDoubleAnimation2, new PropertyPath("(Canvas.Top)"));

    myDoubleAnimation1.To = 200;
    myDoubleAnimation2.To = 200;

    // Make the Storyboard a resource.
    LayoutRoot.Resources.Add("unique_id", sb);

    // Begin the animation.
    sb.Begin();
}
NoteNote:

Do not attempt to call Storyboard methods such as Begin within the constructor of the page. This will cause your animation to fail silently.

Animation Types

The preceding example used a DoubleAnimation to animate a property. In addition to the DoubleAnimation type, Silverlight provides several more animation objects. Because animations generate property values, different animation types exist for different property types. To animate a property that takes a Double value, such as the Width property of an element, use an animation that produces Double values, such as the DoubleAnimation. To animate a property that takes a Point value, use an animation that produces Point values, such as the PointAnimation, and so on.

Silverlight provides two categories of animation types: From/To/By animations and key-frame animations. The following table describes the animation categories and their naming conventions.

Category

Description

Naming convention

From/To/By animation

Animates between a starting and ending value:

  • To specify a starting value, set the From property of the animation.

  • To specify an ending value, set the To property of the animation.

  • To specify an ending value relative to the starting value, set the By property of the animation (instead of the To property).

The examples in this overview use these animations, because they are the simplest to implement.

typeAnimation

Key-frame animation

Animates between a series of values specified using key-frame objects. Key-frame animations are more powerful than From/To/By animations because you can specify any number of target values and even control their interpolation method. Key-frame animations are described in detail in Key-Frame Animations.

typeAnimationUsingKeyFrames

The following table shows several common animation types and some properties that they are used with.

Property type

Corresponding basic (From/To/By) animation

Corresponding key-frame animation

Usage example

Color

ColorAnimation

ColorAnimationUsingKeyFrames

Animate the Color of a SolidColorBrush or a GradientStop.

Double

DoubleAnimation

DoubleAnimationUsingKeyFrames

Animate the Width of a Rectangle or the Height of an Ellipse (or any FrameworkElement)

Point

PointAnimation

PointAnimationUsingKeyFrames

Animate the Center position of an EllipseGeometry.

Object

None

ObjectAnimationUsingKeyFrames

Animate the Fill property from one GradientBrush to another.

Animations Are Timelines

All animations inherit from the Timeline object; therefore, all animations are specialized types of timelines. A Timeline defines a segment of time. You can specify the timing behaviors of a timeline: its Duration, how many times it is repeated, and even how fast it progresses.

Because an animation is a Timeline, it also represents a segment of time. An animation calculates output values as it progresses though its specified segment of time (or Duration). As the animation progresses, or "plays," it updates the property that it is associated with.

Three frequently used timing properties are Duration, AutoReverse, and RepeatBehavior.

Duration Property

A timeline (and therefore, an animation) represents a segment of time. The length of that segment is determined by the Duration property of the timeline, which is usually specified by using a TimeSpan value. When a timeline reaches the end of its duration, it has completed an iteration.

An animation uses its Duration property to determine its current value. If you do not specify a Duration value for an animation, it uses the default value of one second.

The following syntax shows a simplified version of the XAML attribute syntax for the Duration property.

hours : minutes : seconds

The following table shows several Duration settings and their resulting values.

Setting

Resulting value

0:0:5.5

5.5 seconds.

0:30:5.5

30 minutes and 5.5 seconds.

1:30:5.5

1 hour, 30 minutes, and 5.5 seconds.

For more information about Duration values and the XAML syntax, see the Duration property reference page.

AutoReverse Property

The AutoReverse property specifies whether a timeline plays backward after it reaches the end of its Duration. If you set this animation property to true, an animation reverses after it reaches the end of its Duration, playing from its ending value back to its starting value. By default, this property is false.

RepeatBehavior Property

The RepeatBehavior property specifies how many times a timeline plays. By default, a timeline has an iteration count of 1.0, which means it plays one time and does not repeat.

Applying an Animation to a Property

The previous sections describe the different types of animations and their timing properties. This section shows how to apply the animation to the property that you want to animate. Storyboard objects provide one way to apply animations to properties. A Storyboard is a container timeline that provides targeting information for the animations it contains.

Targeting Objects and Properties

The Storyboard class provides the TargetName and TargetProperty attached properties. By setting these properties on an animation, you tell the animation what to animate. However, before an animation can target an object, the object must either be given a name by using the x:Name attribute (as in the previous example), or the property must to be targeted indirectly. The following example demonstrates how to target a property indirectly.

Run this sample

<StackPanel x:Name="myStackPanel" Background="Red"
  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="myStackPanel" 
        Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
        From="Red" To="Green" Duration="0:0:4" />

    </Storyboard>
  </StackPanel.Resources>
</StackPanel>
' Start the animation when the object loads
Private Sub Start_Animation(ByVal sender As Object, ByVal e As EventArgs)
    colorStoryboard.Begin()
End Sub
// Start the animation when the object loads.
private void Start_Animation(object sender, EventArgs e)
{
    colorStoryboard.Begin();
}

Notice that the property value being animated (Color) belongs to a SolidColorBrush object, which is not named or even explicitly declared. This indirect targeting is accomplished by using the following special syntax.

Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"

Alternatively, you can explicitly create the SolidColorBrush, name it, and target its Color property directly. The following example shows how to create the same animation as the previous example, but using direct property targeting.

<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>
' Start the animation when the object loads
Private Sub Start_Animation(ByVal sender As Object, ByVal e As EventArgs)
    colorStoryboard.Begin()
End Sub
// Start the animation when the object loads.
private void Start_Animation(object sender, EventArgs e)
{
    colorStoryboard.Begin();
}

Animating Transforms

Some of the more interesting animations like rotating, skewing, and re-scaling objects are accomplished by animating the properties of Transform objects.

The following example uses a Storyboard and a DoubleAnimation with a RotateTransform to make a Rectangle spin in place.

Run this sample

<StackPanel Margin="15">
  <StackPanel.Resources>
    <Storyboard x:Name="myStoryboard">
      <DoubleAnimation
       Storyboard.TargetName="myTransform"
       Storyboard.TargetProperty="Angle"
       From="0" To="360" Duration="0:0:5" 
       RepeatBehavior="Forever" />
    </Storyboard>
  </StackPanel.Resources>
  <Rectangle Width="50" Height="50" Fill="RoyalBlue"
   MouseLeftButtonDown="StartAnimation">
    <Rectangle.RenderTransform>
      <RotateTransform x:Name="myTransform" Angle="45" CenterX="25" CenterY="25" />
    </Rectangle.RenderTransform>
  </Rectangle>
</StackPanel>
Private Sub StartAnimation(ByVal sender As Object, ByVal e As MouseEventArgs)
    myStoryboard.Begin()
End Sub
private void StartAnimation(object sender, MouseEventArgs e)
{
    myStoryboard.Begin();
}

For more information on transformations, see Transforms.

What Happens After an Animation Ends

The FillBehavior property specifies how a timeline behaves when it ends. The default value for this property is HoldEnd, which means that after an animation ends, the object that was animated holds its final value. For example, if you animate the Opacity property of a Rectangle from 1 to 0 over 2 seconds, the default behavior is for the rectangle to remain at 0 opacity after the 2 seconds elapses. If you set FillBehavior to Stop, the opacity of the rectangle reverts to its original value of 1 after the animation ends.

Easing Functions

Easing functions allow you to apply custom mathematical formulas to your animations. For example, you may want an object to realistically bounce or behave as though it were on a spring. You could use Key-Frame or even From/To/By animations to approximate these effects but it would take a significant amount of work and the animation would be less accurate than using a mathematical formula.

Besides creating your own custom easing function by inheriting from EasingFunctionBase, you can use one of several easing functions provided by the runtime to create common effects.

  • BackEase: Retracts the motion of an animation slightly before it begins to animate in the path indicated.

  • BounceEase: Creates a bouncing effect.

  • CircleEase: Creates an animation that accelerates and/or decelerates using a circular function.

  • CubicEase: Creates an animation that accelerates and/or decelerates using the formula f(t) = t3.

  • ElasticEase: Creates an animation that resembles a spring oscillating back and forth until it comes to rest.

  • ExponentialEase: Creates an animation that accelerates and/or decelerates using an exponential formula.

  • PowerEase: Creates an animation that accelerates and/or decelerates using the formula f(t) = tp where p is equal to the Power property.

  • QuadraticEase: Creates an animation that accelerates and/or decelerates using the formula f(t) = t2.

  • QuarticEase: Creates an animation that accelerates and/or decelerates using the formula f(t) = t4.

  • QuinticEase: Create an animation that accelerates and/or decelerates using the formula f(t) = t5.

  • SineEase: Creates an animation that accelerates and/or decelerates using a sine formula.

You can explore the behavior of these easing functions with the following sample.

Run this sample

To apply an easing function to an animation, use the EasingFunction property of the animation specify the easing function to apply to the animation. The following example applies a BounceEase easing function to a DoubleAnimation to create a bouncing effect.

Run this sample

<StackPanel x:Name="LayoutRoot" Background="White">
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimation From="30" To="200" Duration="00:00:3" 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="Height">
                <DoubleAnimation.EasingFunction>
                    <BounceEase Bounces="2" EasingMode="EaseOut" 
                                Bounciness="2" />
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </StackPanel.Resources>

    <Rectangle x:Name="myRectangle" MouseLeftButtonDown="Mouse_Clicked" 
     Fill="Blue" Width="200" Height="30" />

</StackPanel>
' When the user clicks the rectangle, the animation
' begins. 
Private Sub Mouse_Clicked(ByVal sender As Object, ByVal e As MouseEventArgs)
    myStoryboard.Begin()
End Sub
// When the user clicks the rectangle, the animation
// begins. 
private void Mouse_Clicked(object sender, MouseEventArgs e)
{
    myStoryboard.Begin();
}

In the previous example, the easing function was applied to a From/To/By animation. You can also apply these easing functions to Key-Frame animations (see Key-Frame Animations). The following example shows how to use key frames with easing functions associated with them to create an animation of a rectangle that contracts upward, slows down, then expands downward (as though falling) and then bounces to a stop.

Run this sample

<StackPanel x:Name="LayoutRoot" Background="White">
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimationUsingKeyFrames
             Storyboard.TargetProperty="Height"
             Storyboard.TargetName="myRectangle">

                <!-- This keyframe animates the ellipse up to the crest 
                     where it slows down and stops. -->
                <EasingDoubleKeyFrame Value="30" KeyTime="00:00:02">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <CubicEase EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>

                <!-- This keyframe animates the ellipse back down and makes
                     it bounce. -->
                <EasingDoubleKeyFrame Value="200" KeyTime="00:00:06">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <BounceEase Bounces="5" EasingMode="EaseOut"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>

            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </StackPanel.Resources>

    <Rectangle x:Name="myRectangle" MouseLeftButtonDown="Mouse_Clicked" 
     Fill="Blue" Width="200" Height="200" />
</StackPanel>
' When the user clicks the rectangle, the animation
' begins. 
Private Sub Mouse_Clicked(ByVal sender As Object, ByVal e As MouseEventArgs)
    myStoryboard.Begin()
End Sub
// When the user clicks the rectangle, the animation
// begins. 
private void Mouse_Clicked(object sender, MouseEventArgs e)
{
    myStoryboard.Begin();
}

You can use the EasingMode property to alter how the easing function behaves, that is, change how the animation interpolates. There are three possible values you can give for EasingMode:

  • EaseIn: Interpolation follows the mathematical formula associated with the easing function.

  • EaseOut: Interpolation follows 100% interpolation minus the output of the formula associated with the easing function.

  • EaseInOut: Interpolation uses EaseIn for the first half of the animation and EaseOut for the second half.

The graphs below demonstrate the different values of EasingMode where f(x) represents the animation progress and t represents time.

BackEase

BackEase EasingMode graphs.

BounceEase

BounceEase EasingMode graphs.

CircleEase

CircleEase EasingMode graphs.

CubicEase

CubicEase EasingMode graphs.

ElasticEase

ElasticEase with graphs of different easingmodes.

ExponentialEase

ExponentialEase graphs of different easingmodes.

PowerEase

QuarticEase with graphs of different easingmodes.

QuadraticEase

QuadraticEase with graphs of different easingmodes

QuarticEase

QuarticEase with graphs of different easingmodes.

QuinticEase

QuinticEase with graphs of different easingmodes.

SineEase

SineEase graphs.

NoteNote:

You can use PowerEase to create the same behavior as CubicEase, QuadraticEase, QuarticEase, and QuinticEase by using the Power property. For example, if you want to use PowerEase to substitute for CubicEase, specify a Power value of 3.

In addition to using the easing functions included in the run-time, you can create your own custom easing functions by inheriting from EasingFunctionBase. The following example demonstrates how to create a simple custom easing function. You can add your own mathematical logic for how the easing function behaves by overriding the EaseInCore method.

Run this sample

namespace CustomEasingFunction
{
    public class CustomSeventhPowerEasingFunction : EasingFunctionBase
    {
        public CustomSeventhPowerEasingFunction() : base() 
        { 
        }   

        // Specify your own logic for the easing function by overriding
        // the EaseInCore method. Note that this logic applies to the "EaseIn"
        // mode of interpolation. 
        protected override double EaseInCore(double normalizedTime) 
        { 
            // applies the formula of time to the seventh power.
            return Math.Pow(normalizedTime, 7);
        }

    }
}

Custom Animations

Occasionally, typical animations and even custom easing functions will not meet your needs. For example, if you want an animation that uses collision detection, you could create a custom per-frame animation. In this way, your custom animation can bypass the Silverlight animation system. For more information, see Custom Animations in Silverlight.