Animation is very useful in creating graphically rich Silverlight applications. This posting illustrates the use of several types of animation in Silverlight, including key frames and splines, in order to simulate a bouncing ball.

The Zip file, BouncingBall.zip, contains all the files used for this sample. You can also run the Silverlight application by clicking the button below:

Click to run sample

Defining a TransformGroup
A transform can be used with an element to create effects, such as motion and scaling.  A TranslateTransform moves (translates) an element by its X and Y values. A ScaleTransform scales an element by its ScaleX and ScaleY values. In this sample, both a ScaleTransform and a TranslateTransform are applied to an Ellipse object that represents a bouncing ball.

The RenderTransform property allows you to define transforms for the Ellipse element. Since multiple transforms are defined, a TransformGroup is defined to contain the collection of transforms:

<Ellipse.RenderTransform>
  <
TransformGroup>
    <
TranslateTransform x:Name="myTranslate"/>
    <
ScaleTransform x:Name="myScale"/>
  </
TransformGroup>
</
Ellipse.RenderTransform>

The TranslateTransform is used to provide motion by modifying the X and Y values of the bouncing ball. Since an animation can be associated with this type of transform, the x:Name value is defined so that it can be referenced in the animation definition.

The ScaleTransform is used to slightly modify the size of bouncing ball at its lowest point of impact, giving a flattening effect. Again, the x:Name value is defined, so that it can be referenced in the animation definition.

Defining an EventTrigger and a Storyboard
For an animation effect to be active, it needs to be associated with an EventTrigger, which describes what actions to take when a specified event occurs. The RoutedEvent property allows you to define an EventTrigger for the Ellipse. The event that will be associated with these animations is Loaded, which is fired when the Ellipse object has been rendered and is ready for interaction:

<Ellipse.Triggers>
  <
EventTrigger RoutedEvent="Ellipse.Loaded">
    <
BeginStoryboard>
      <
Storyboard>
        <!-- Animation definitions -->
      </
Storyboard>
    </
BeginStoryboard>
  </EventTrigger>
</
Ellipse.Triggers>

The BeginStoryboard object is a type of TriggerAction that applies and starts the animations defined in a Storyboard.

  A Closer Look at the Animation Definitions   

There are four animations defined for the bouncing ball. Two animations control the movement of the X and Y values of the ball, which represent the position of the ball. Two additional animations control the ScaleX and ScaleY values, which represent the width and height of the ball. 

Animating the X Value
The X value is animated by a type DoubleAnimation. This animation simply moves the ball along the x-axis at a constant rate:

<!-- Animation for X value -->
<DoubleAnimation
  Duration="0:0:10"
  Storyboard.TargetName="myTranslate"
  Storyboard.TargetProperty="X"
  To="700"
  AutoReverse="True"
  RepeatBehavior="Forever"/>

The To value determines how far on the x-axis to move. The Duration value specifies the time length of the animation -- in this case, 10 seconds. The AutoReverse value states that the animation should reverse itself after the duration. Finally, the RepeatBehavior value states that the animation loops forever.

Ball moves back and forth along x-axis

Animating the Y Value
The Y value is animated by a type DoubleAnimationUsingKeyFrames, and uses both LinearDoubleKeyFrame and SplineDoubleKeyFrame objects to create a variable rate of change in the ball's up and down motion. This results in the ball having a more realistic bounce by accelerating and decelerating the motion:

<!-- Animation for Y value -->
<
DoubleAnimationUsingKeyFrames
 
Duration="0:0:4.5"
  Storyboard.TargetName="myTranslate"
  Storyboard.TargetProperty="Y"
  RepeatBehavior="Forever">
  <
LinearDoubleKeyFrame
   
Value="0" KeyTime="0:0:0"/>
  <
SplineDoubleKeyFrame
    Value="375" KeyTime="0:0:2.2"
  
 KeySpline="0, 0, 0.5, 0"/>
  <
LinearDoubleKeyFrame
  
 Value="375" KeyTime="0:0:2.25"/>
  <
SplineDoubleKeyFrame
  
 Value="0" KeyTime="0:0:4.5"
  
 KeySpline="0, 0, 0, 0.5"/>
</
DoubleAnimationUsingKeyFrames>

The Duration value of the DoubleAnimationUsingKeyFrames object refers to the total length of time that the key frames represents. The object references the TranslateTransform that is named "myTranslate". Whereas the DoubleAnimation references the X value of the transform, the DoubleAnimationUsingKeyFrames object references the Y value of the transform, causing the bouncing ball to move along the y-axis.

Bouncing ball moving along y-axis

The LinearDoubleKeyFrame objects reference specific values of the Y value at specific times in the animation, causing the element to animate at a constant, or linear, rate of speed. You could create this effect by modifying the sample, and using only LinearDoubleKeyFrame objects -- this means removing the SplineDoubleKeyFrame objects:

<DoubleAnimationUsingKeyFrames
  ...
  <!-- Using only LinearDoubleKeyFrame objects -->

  <
LinearDoubleKeyFrame
   
Value="0" KeyTime="0:0:0"/>
  <
SplineDoubleKeyFrame           
    Value="375" KeyTime="0:0:2.2
  
 KeySpline="0, 0, 0.5, 0"
/>    
  <
LinearDoubleKeyFrame
   
Value="0" KeyTime="0:0:2.25"/>
  <
SplineDoubleKeyFrame           
  
 Value="0" KeyTime="0:0:4.5"   
  
 KeySpline="0, 0, 0, 0.5"
/>    
  <
LinearDoubleKeyFrame           
  
 Value="375" KeyTime="0:0:4.5"/>

The way to create more realistic acceleration and deceleration effects to key frames is to create splined interpolation, which allows you to create a variable rate of change in a value based on a calculation. Notice the use of two SplineDoubleKeyFrame objects in the DoubleAnimationUsingKeyFrames definition. These objects cause the bouncing ball to accelerate toward the end of its downward path, and decelerate towards the end of its upward path.

<DoubleAnimationUsingKeyFrames
  ...
  <
SplineDoubleKeyFrame
    Value="375" KeyTime="0:0:2.2"
  
 KeySpline="0, 0, 0.5, 0"/>
  ...
  <SplineDoubleKeyFrame
  
 Value="0" KeyTime="0:0:4.5"
  
 KeySpline="0, 0, 0, 0.5"/>

The KeySpline values of the SplineDoubleKeyFrame objects define quadratic Bezier curves. The resulting curves specify how an animation is interpolated during a time segment; that is, the curve represents the rate of change in the animation's target attribute over the time segment.

Bezier curves

Animating the ScaleX Value
The ScaleX value is animated by a type DoubleAnimationUsingKeyFrames, which uses a set of four LinearDoubleKeyFrame objects. The KeyTime property of the LinearDoubleKeyFrame objects is synchronized with the preceding animation so that the maximum change to the width of the bouncing ball occurs when the ball is at its lowest point.

Notice that the flattening effect does not start until the KeyTime value is at 2.15 seconds, which is just before it reaches the point of impact. In addition, the ball is restored to its original width at 2.5 seconds. This means the flattening effect occurs briefly at the lowest point of the ball's bounce. Changing the Value property to 1.2, or 120% of the width, has the effect of slightly increasing the width of the ball:

<!-- Animation for ScaleX value -->
<
DoubleAnimationUsingKeyFrames
 
Duration="0:0:4.5"
  Storyboard.TargetName="myScale"
  Storyboard.TargetProperty="ScaleX"
  RepeatBehavior="Forever">
  <
LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
  <
LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.15"/>
  <
LinearDoubleKeyFrame Value="1.2" KeyTime="0:0:2.25"/>
  <
LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
</
DoubleAnimationUsingKeyFrames>

Animating the ScaleY Value
The ScaleY value is animated by a type DoubleAnimationUsingKeyFrames, which also uses a set of four LinearDoubleKeyFrame objects. The KeyTime property of the LinearDoubleKeyFrame objects is synchronized with the preceding animation so that the maximum change to the height of the ball occurs when the ball is at its lowest point. Changing the Value property to 0.7, or 70% of the height, has the effect of slightly decreasing the height of the ball:

<!-- Animation for ScaleY value -->
<
DoubleAnimationUsingKeyFrames
 
Duration="0:0:4.5"
  Storyboard.TargetName="myScale"
  Storyboard.TargetProperty="ScaleY"
  RepeatBehavior="Forever">
  <
LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
  <
LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.15"/>
  <
LinearDoubleKeyFrame Value="0.7" KeyTime="0:0:2.25"/>
  <
LinearDoubleKeyFrame Value="1" KeyTime="0:0:2.5"/>
</
DoubleAnimationUsingKeyFrames
>

Silverlight SDK Overviews
For more information on Silverlight animation support, see Animation Overview, Interactive Animations Overview, and Key-Frame Animations Overview. The Silverlight 1.0 Beta Quickstart also provides a good starting point for exploring animation support.

Enjoy,
Lorin
Silverlight SDK Team