brandon
brandon

Reputation: 374

Programmatically create silverlight animation with easing in C#

I'm messing around with making a clock in silverlight. I am trying to set up the animation code programmatically because I want to reuse the same code for each of the 3 clock hands (and I don't think I can do this with a single storyboard in xaml).

        public void Rotate(double toAngle, RotateTransform rotate)
    {
        Storyboard sb = new Storyboard();

        DoubleAnimationUsingKeyFrames keyframes = new DoubleAnimationUsingKeyFrames();

        EasingDoubleKeyFrame easingStart = new EasingDoubleKeyFrame();
        easingStart.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
        easingStart.Value = rotate.Angle;

        EasingDoubleKeyFrame easingEnd = new EasingDoubleKeyFrame();
        easingEnd.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
        easingEnd.Value = toAngle;
        var ease = new ElasticEase();
        ease.EasingMode = EasingMode.EaseIn;
        easingEnd.EasingFunction = ease;

        keyframes.KeyFrames.Add(easingStart);
        keyframes.KeyFrames.Add(easingEnd);

        Storyboard.SetTarget(keyframes, rotate);
        Storyboard.SetTargetProperty(keyframes, new PropertyPath("(RotateTransform.Angle)"));

        sb.Children.Add(keyframes);
        sb.Begin();
    }

I pass in both the angle I want the current hand to rotate to and the rotate transform for that hand. From this rotate transform I get the starting angle.

When I run the clock, the clock hands move (the second hand moves to the correct spot each second etc) but the animations don't appear to actually animate. They just go from start to end instantly.

Why does the animation not happen properly?

Upvotes: 1

Views: 1986

Answers (1)

iCollect.it Ltd
iCollect.it Ltd

Reputation: 93611

The skipping problem is likely the lag in starting a storyboard that wants to show changes in less than a second. By the time the storyboard gets itself ready to display it basically says "oh... it's after 1 second now, where should I be now". You are better off with longer storyboards.

I'm not sure how much control you are wanting over your clock, but regarding using a single storyboard, here goes...

I was not sure of the overall problem you are trying to solve, but the following example uses one simple storyboard to run the 3 hands of a clock. The only problem I had was that the maximum time interval I could specify for the hour hand (in XAML), without a parsing error, is 23:59:59.

    <Storyboard x:Name="SecondHandStoryboard" RepeatBehavior="Forever">
        <DoubleAnimation Duration="0:1:0" To="360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="SecondHand" />
        <DoubleAnimation Duration="1:0:0" To="360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="MinuteHand"/>
        <DoubleAnimation Duration="23:59:59" To="360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="HourHand"/>
    </Storyboard>

I actually wanted to add a solid "tick" animation to the second hand, but have not figured out how to get rotation "by" storyboards to work. Basically use a repeated 6 degree per-second 1-second long storyboard with steep easing-in (will keep looking into that problem).

Anyway, hope this is of help to you.

Upvotes: 1

Related Questions