Animations are something that many do not take in serious considerations, just because too often in the development of applications they are considered something incidental. Nevertheless it is really important to know the matter because there are many cases where an animation is something that make your application more pleasant and effective. Also, you may have the need of take advantage of the VisualStateManager so knowing animations and storyboards become something crucial, no matter if we have a very powerful allied named Blend.
In Silverlight, the concept of creating an animation is simple and may be resumed in a short sentence: take a dependency property and change its value along time. First of all you have to be aware that, only Dependency Properties can be affected by an animation because of their special behavior. Second you have also to know that, depending on the type of the target property you have to use a specific type of animation. So, if you want to animate the Width property of a rectangle you have to use an animation that is capable of manipulating a value of type double. A limited number of types are available in Silverlight, but it is demonstrated that they suffice for the most of the cases. Here is the available types:
DoubleAnimation: can be used for animate properties of type double. It is the type that solve the great number of cases.
ColorAnimation: It is capable of animate a color, changing the value along a gradient calculated at runtime. Important to note that it apply to the type Color and not to a Brush
PointAnimation: It animates a Point structure. It is useful to make objects move along a path.
Side by side with linear animations - I call them with this name because the variation of the value follow a linear scale - there are a complete set of key frame animations that are able to express the variation of the value over a series of "chunks" that define a complex path. So, as and example, with a DoubleAnimationUsingKeyFrames you can start from a value, move linearly to another one and continue with another again and so on. Keyframes are interesting for coordinating the flow of complex animations.
Doing an animation is simple. After the choice of the type you are targeting you have to setup some values that tell how the animation must work. An animation has an huge number of properties you can use to tune its behavior but for the sake of this post I resume the most important in the following table:
From, To and By |
The properties define the boundaries of the value to animate. From define the start and and undefined value means starting from the current value of the property. To define the end of the animation and By define the amount to add at every tick. |
Duration |
Tell the total duration of the animation. This value is not final but may be affected by other properties. As an example, SpeedRatio can shorten the duration. |
SpeedRatio |
Define the speed of the animation with a speed factor. This may be useful to change the speed of an animation without changing its Duration property. |
BeginTime |
Define the timeout after which the animation will start. Is is often useful to coordinate different animations planning cascade effects. |
FillBehavior |
Define the behavior of the animation at the end. It may be HoldEnd that is the property remain at the last value or Stop means that the value return at the begin. |
RepeatBehavior |
This indicate if the animation have to repeat a number of times after the end. As an example, 2x tells to repeat two times. Forever indicate an infinite loop. |
AutoReverse |
Ask the animation to return to the initial value following the path backward. This property double the Duration of the animation. |
Storyboard.TargetName |
This attached property defines the name of the element in the DOM that is affected by the animation |
Storyboard.TargetProperty |
This attached property defines the property of the element that is the target of the animation. |
Define a Storyboard
The classes I've illustrated until to this point are completely not useful if there is nothing able to coordinate them. It is clear that the limit of animating only one property at the time is unacceptable in a real world application. Most of the times indeed you have to manipulate a number of properties and possibly coordinate them to get a good result.
For this purpose it exists the Storyboard that is a class that derive from Timeline, like all the animations do. The difference is that the Storyboard collects a number of animations together and let the developer to act like they are a single item.
Beyond the point of manipulating multiple animations, you have to known that the Storyboard is the very starting point, also for a single animation. It is indeed required you use a Storyboard for controlling the animation lifetime. It exposes the Begin, Pause, Resume and Stop methods that have an obvious meaning. So here is a simple Storyboard:
1: <UserControl.Resources>
2: <Storyboard x:Name="sbRotate">
3: <DoubleAnimation From="0" To="360" Duration="00:00:10.000" SpeedRatio="1"
4: Storyboard.TargetName="targetTransform"
5: Storyboard.TargetProperty="Rotation" />
6: </Storyboard>
7: </UserControl.Resources>
As you can see I've added the Storyboard to the Resources section of the UserControl. If you define it in XAML this is the best solution. The contained animation change a double value from 0 to 360 in 10 seconds and the value is applied to a CompositeTrasform called "targetTransform" on the property "Rotation". It is evident that the result will be the complete rotation of the element around the center of the transform. You can also compose complex animations like the one I present here:
1: <UserControl.Resources>
2: <Storyboard x:Name="sbRotate">
3: <DoubleAnimation From="0" To="360" Duration="00:00:10.000" SpeedRatio="1"
4: Storyboard.TargetName="targetTransform"
5: Storyboard.TargetProperty="Rotation" />
6: <Storyboard BeginTime="00:00:05">
7: <DoubleAnimation From="1" To="2" Duration="00:00:1.000" SpeedRatio="1"
8: Storyboard.TargetName="targetTransform" Storyboard.TargetProperty="ScaleX" />
9: <DoubleAnimation From="1" To="2" Duration="00:00:1.000" SpeedRatio="1"
10: Storyboard.TargetName="targetTransform" Storyboard.TargetProperty="ScaleY" />
11: </Storyboard>
12: </Storyboard>
13: </UserControl.Resources>
Here I compose the previous animation with another Storyboard containing two more animations applied to the ScaleX and ScaleY properties. The inner Storyboard is used to shift the beginning of the scale animation by 5 seconds. It is possible because both the animations and the Storyboard inherits from Timeline.
After composing the animation in XAML you can start it at a give point using codebehind. Silverlight does not support triggers so differently from WPF it is the sole way for working with Storyboards:
1: void MainPage_Loaded(object sender, RoutedEventArgs e)
2: {
3: this.sbRotate.Begin();
4: }
This is also the reason why I've decided to use a x:Name attribute in resources instead of the usual x:Key. The x:Name in fact generates the codebehind reference so I've it available to command the Storyboard.