Declarative Tweening
(Series Link: Part 1, Part 2, Part 3, Part 4)
Since I started working on the next version of my Slideshow application, I have this fascination with Tweening. Tweening is the process of creating a (complex) animation based on a start frame and end frame. Silverlight supports animations out of the box in the form of Linear, Discrete and Splined animations for doubles, points and colors. Unfortunately, these animations have some limitations. Michael Cameron describes them in his excellent post on Tweening for Silverlight. The main limitation is that standard Silverlight animation types do not support overshoot, undershoot, elastic and bounce type transitions.
Tweener provides implementations for all kind of complex animations including those elastics, overshoot, etc. animation types. Originating from the Flash scene, a number of Tweener libraries have been created for Silverlight. The most well-known is probably agTweener ported by Michael Cameron. Another Tweener library, created by Christian Merighi, can be found here.
Problem
I like these libraries, complex Tweening animations made simple and it just works. However there is one major problem that I personally have with the current Tweener implementations for Silverlight. The Tweener libraries require the developer to create animations in code. There is no solution where a Tweening animation can be defined in XAML alone. The libraries use an empty Storyboard (or worse a DispatchTimer) to handle the animation steps and this is a solution that doesn't integrate well with the built-in animation support of Silverlight. The VisualStateManager for example doesn't work with Tweener libraries, it requires a Storyboard declared in XAML. A control designer does not have the ability to use a Tweener animation to move from one control state to the other.
And I want to do exactly that. I want to customize a Button control with Tweening animations so that it bounces on my screen when I hover the mouse over it. And I have found a solution.
Solution
Use the Tweener library to generate a Storyboard with animations using key frames. The DoubleAnimationUsingKeyFrames animation is a perfect candidate for this. Each generated linear keyframe corresponds to a step in the Tweener animation.
Let share some code. The following code-snippet demonstrates the creation of N LinearDoubleFrames based on a start and end value and the duration of an animation. The code creates the key frames for a EaseInQuad Tweener animation.
double from = 0;
double to = 100;
double total = animation.Duration.TimeSpan.TotalMilliseconds;
for (double i = 0; i < total; i += 50) {
LinearDoubleKeyFrame frame = new LinearDoubleKeyFrame();
frame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(i));
frame.Value = EaseInQuad(i, from, to - from, total);
animation.KeyFrames.Add(frame);
}
public static double EaseInQuad(params double[] args)
{
double t; double b; double c; double d;
t = args[0]; b = args[1]; c = args[2]; d = args[3];
return c * (t /= d) * t + b;
}
In order to make things fully declarable in XAML, I defined a number of attached dependency properties which make up a Tweener animation. The three attached properties are To, From and TweenerType. When attached to a DoubleAnimationUsingKeyFrame, the animation is automatically filled with the corresponding key frames.
This is what the end result looks like.
<Storyboard x:Name="storyboard" AutoReverse="True" RepeatBehavior="Forever" > <DoubleAnimationUsingKeyFrames Storyboard.TargetName="rect" Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:3" ff:Tween.Type="EaseOutBounce" ff:Tween.From="10" ff:Tween.To="300" /> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="rotate" Storyboard.TargetProperty="Angle" Duration="0:0:3" ff:Tween.Type="EaseOutElastic" ff:Tween.From="0" ff:Tween.To="180" /> </Storyboard>
And here is an actual demonstration of the above code:
So, what have we achieved here? Declarative Tweening! Full support of all Tweening animations (including overshoot, undershoot, elastic and bounce type transitions) while being fully compliant with the Storyboard framework. Now, I can customize the Button with some cool elastic effect without having to write a single line of code. How cool is that?
Download the source code
(Series Link: Part 1, Part 2, Part 3, Part 4)
4 Comments
Timmy said:
Hi Koen, I think I understand what you are trying to do here. Do you have an example where this Tweener library of yours is used when customizing controls?
Koen said:
Hi Timmy, I'm working on a sample where a customized button uses Tweening animations for the button states and transitions. Will post it as soon as it's done.
Koen said:
Timmy; Part 4 of this blog post series on Tweening contains an example of a customized button using tween animations. Hope this helps
Jeremy said:
This is very slick. Thanks for sharing

