Mobile Zone is brought to you in partnership with:

I've been working with Microsoft technologies since 2006. ALT.NET developer, always keeping an eye out for a better way. Mariano is a DZone MVB and is not an employee of DZone and has posted 15 posts at DZone. You can read more from them at their website. View Full User Profile

Progress Control Animations for Windows Store Apps with XAML and C#

12.24.2012
| 2562 views |
  • submit to reddit

In this post, I'm going to show you how you can create a circular animation in a metro style application (XAML/C#). In my case, we needed to animate a circular progress arc that fires when the user waits for some process to complete. In this case, we're going to use a full 360° animation, but take into account that you can go up to any angle you want (if that's your scenario).

I developed a sample so you can test this approach, you can find it here. Feel free to use it in your app, modify it (and do whatever you want).

The XAML

We animate two ArcSegments inside a Path. The Data attribute contains the value of the initial values (position zero).

<Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
    <Path x:Name="progressPath" Stroke="Gold" StrokeThickness="5" 
          HorizontalAlignment="Center" VerticalAlignment="Center" Height="305" Width="305"
          Data="m 150,0 A 150,0 0 0 0 150,0 A 150,150 0 0 0 150,0" />
</Grid>

The code (C#)

I think the code speaks for itself: we create a storyboard to animate the Data attribute. Given an angle, we calculate the point in the circle using sin and cos (math rocks!) and create a DiscreteObjectKeyFrame to animate the transition. We do this for all angles between 0 and the final angle (with 1° steps). Lastly, the first ArcSegment is for the angles between 0 a 180, and the second are for the rest.

public static void AnimatePath(Windows.UI.Xaml.Shapes.Path progressPath, double radius, Point initialPoint, double finalAngle = 180, double timeStep = 0.01)
{
    var storyboard = new Storyboard();

    var progressAnimation = new ObjectAnimationUsingKeyFrames();
    Storyboard.SetTarget(progressAnimation, progressPath);
    Storyboard.SetTargetProperty(progressAnimation, "(Path.Data)");

    Point center = new Point(radius, radius);
    for (int i = 0; i <= finalAngle; i++)
    {
        var discreteObjectKeyFrame = new DiscreteObjectKeyFrame();
        discreteObjectKeyFrame.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(i * timeStep));

        // create points for each ArcSegment
        Point firstArcPoint = new Point(radius, 0);
        Point secondArcPoint = new Point(radius, 0);

        if (i < 180)
        {
            // calculate a new point of the first ArcSegment
            firstArcPoint.X = Math.Cos(Math.PI * (270 - i) / 180.0) * radius + center.X;
            firstArcPoint.Y = Math.Sin(Math.PI * (270 - i) / 180.0) * radius + center.Y;
            secondArcPoint = firstArcPoint;
        }
        else
        {
            // leave the first ArcSegment static and calculate a new point of the second
            firstArcPoint = new Point() { X = radius, Y = radius * 2 };
            secondArcPoint.X = Math.Cos(Math.PI * (270 - i) / 180.0) * radius + center.X;
            secondArcPoint.Y = Math.Sin(Math.PI * (270 - i) / 180.0) * radius + center.Y;
        }

        // for instance, a complete circle with a radius of 150: "m 150,0 A 150,150 0 0 0 150,300 A 150,150 0 0 0 150,0"
        string dataValue = "m {0},{1} A {2},{2} 0 0 0 {3},{4} A {2},{2} 0 0 0 {5},{6}";
        discreteObjectKeyFrame.Value = string.Format(dataValue, initialPoint.X, initialPoint.Y, radius, firstArcPoint.X, firstArcPoint.Y, secondArcPoint.X, secondArcPoint.Y);
        progressAnimation.KeyFrames.Add(discreteObjectKeyFrame);
    }   

    storyboard.Children.Add(progressAnimation);
    storyboard.Begin();
}

Below you can find a video with the result:

And that's it! Remember that you can check out the code here

Note: for a smoother animation, you can use 0.5° steps (or less). I decided to leave it in 1° here just to make the code simpler.

Published at DZone with permission of Mariano Vazquez, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)