Reusable WPF/Silverlight Animations

As I was working on fixing some animations that got broken due to splitting on one control into multiple controls, I came up with an idea of creating a single animation that could be apply to multiple controls.  In my case, the animation was two-fold.  As control came into view, it should fade into the view as well as "bounce".  Essentially, this animation utilizes scale transform and opacity transform.  Here is the new class I wrote.  The cool thing is that this class can be called with any UI element or control.As a matter of fact, the control does not even need to have transform group defined for it, as the class will create one on the fly to support desired animation.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Media.Animation;
using System.Windows;
using System.Windows.Media;

namespace App.Animation
{
    public static class InitialControlAnimation
    {
        public static void Play(UIElement controlToAnimate)
        {
            Storyboard story = new Storyboard();

            // opacity animation
            DoubleAnimationUsingKeyFrames opacityAnimation = new DoubleAnimationUsingKeyFrames();
            opacityAnimation.BeginTime = TimeSpan.FromMilliseconds(0);
            opacityAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))));
            opacityAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0.8, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200))));
            opacityAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300))));
            ((SplineDoubleKeyFrame)opacityAnimation.KeyFrames[2]).KeySpline = new KeySpline(0, 1, 1, 1);
            Storyboard.SetTarget(opacityAnimation, controlToAnimate);
            Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(UIElement.OpacityProperty));
            story.Children.Add(opacityAnimation);

            //stretch horizontally
            DoubleAnimationUsingKeyFrames scaleXAnimation = new DoubleAnimationUsingKeyFrames();
            scaleXAnimation.BeginTime = TimeSpan.FromMilliseconds(0);
            scaleXAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0.95, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))));
            scaleXAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(1.08, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200))));
            scaleXAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300))));
            Storyboard.SetTarget(scaleXAnimation, controlToAnimate);
            Storyboard.SetTargetProperty(scaleXAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
            story.Children.Add(scaleXAnimation);

            //stretch vertically
            DoubleAnimationUsingKeyFrames scaleYAnimation = new DoubleAnimationUsingKeyFrames();
            scaleYAnimation.BeginTime = TimeSpan.FromMilliseconds(0);
            scaleYAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(0.95, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0))));
            scaleYAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(1.08, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(200))));
            scaleYAnimation.KeyFrames.Add(new SplineDoubleKeyFrame(1, KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(300))));
            Storyboard.SetTarget(scaleYAnimation, controlToAnimate);
            Storyboard.SetTargetProperty(scaleYAnimation, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
            story.Children.Add(scaleYAnimation);

            if (!(controlToAnimate.RenderTransform is TransformGroup))
            {
                TransformGroup group = new TransformGroup();
                group.Children.Add(new ScaleTransform(1, 1, controlToAnimate.RenderSize.Height / 2, controlToAnimate.RenderSize.Width / 2));
                controlToAnimate.RenderTransform = group;
            }
            story.Begin();

        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *