Feed on
Posts
Comments

A common UI metaphor in recent times is the circular wait cursor or progress indicator. This article shows some easy techniques within Expression Blend 2 that simplify creating this modern UI indicator. After showing how to easily layout multiple child elements in a 360-degree pattern, I will show animation techniques for spinning, sizing and fading sub-elements.

Part Two

In the first installment of this article I showed some techniques for implementing circular animations. The trek continues in this installment where I will show you how to arrange elements evenly about the perimeter of a circle and how to recreate the Silverlight loading animation.

[Arranging Shapes in a Circle with Expression Blend, Part One]

Evenly Placing Elements Around a Center Point

The Expression Blend designer makes it easy to arrange items around the perimeter of a circle. Arranging shapes in this fashion is a common UI pattern. Take this simulated clock face (Figure 1) for example. It has 12 rectangles arranged evenly about the outer rim.  Not only are they equal distance apart but each rectangle is also angled at 30 degrees from its neighbors.

image

Figure 1: Simple clock face.

The kaleidoscopic patterns that emerge from these simple curved arrangements are boundless.  I could change the rectangles to triangles and hide the underlying circle and suddenly have a pattern that suggests the outline of a stylized sun. For the next demonstration I will create a pattern of green triangles (Figure 2) pointing outward like points of a compass.

image

Figure 2: Eight triangle pattern.

The repetitive pattern (Figure 2) is generated from a humble green triangle (Figure 3) below, which is created with the Path class (watch Video 1).

image

Figure 3: Green triangular path.

Video 1: Creating triangle path.

The Blend Artboard provides five control points for manipulating an element’s rotation transform with your mouse.  The four corner points (corner white dots in Figure 4) are interactive handles that you can use to spin the object thereby changing the rotation angle property. Normally the center point is exactly that – centered within the shape bounding rectangle.  But it doesn’t have to stay there.

The white dot in the center of the green triangle (Figure 4) is the fifth control point and it controls where the center of the rotation will occur. If you drag this center point to a new location it changes the CenterPoint property and it will affect future rotations.

image 

Figure 4: The rotation controls points.

To make my pattern I want to rotate each triangle 45 degrees from its neighbors. The pattern won’t look right if you use the default center point however.  Instead I want each of the triangles in the pattern to share a common center point (the center of the larger circle).

image

Figure 5: Common center point.

It’s painless to do this in Blend as long as you know the steps to follow. I’ve recorded a short video (Video 2) that walks you through the actions necessary to make this pattern.

Video 2: Event spacing of elements.

 

That’s it.  Now that you have the pattern finished it is simple to make a 360-degree animation from the composite parts (Video 3).

Video 3: Even spacing finished.

Silverlight Animation

It’s time to put some pizzazz in our animations.  To mimic the Silverlight animation I need to build my UI from blue circles instead of green triangles. Each blue circle needs to animate independently from the others as it whirls about the edge of the circle.  I could choose to use a variety of effects.  I could spin the shape, have it fade slowly out of sight or make it jiggle about as it spins.  Since each shape needs to run an animation on its own timeline I will encapsulate this behavior in a user control.

Microsoft uses a similar technique for the Silverlight loading animation.  Watch this video of the Silverlight animation (Video 4) to see how they implemented the animation.  Note that the dots do not spin about the circle.  Instead each blue dot grows into view and then quickly disappears.

Video 4: the Sliverlight animation.

Create the Blue Dot

As I mentioned in the last section I want to encapsulate the animated dot within a UserControl. I created the BlueDot user control in Expression Blend using the following steps.  First I added a UserControl to the project and then I added an ellipse to the main Grid.  I made the ellipse stroke invisible and changed the fill to a radial gradient brush. After fussing around with the brush for a few minutes I ended up with four gradients stops in the gradient.  Each gradient stop uses a varying degree of transparency to achieve a banded effect for the ellipse (Figure 6).

image

Figure 6: The four gradients.

The snippet below shows the finished XAML for the BlueDot ellipse.

<Ellipse Stroke="{x:Null}" x:Name="ellipse" RenderTransformOrigin="0.5,0.5">
            <Ellipse.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="0" ScaleY="0"/>
                    <SkewTransform AngleX="0" AngleY="0"/>
                    <RotateTransform Angle="0"/>
                    <TranslateTransform X="0" Y="0"/>
                </TransformGroup>
            </Ellipse.RenderTransform>
            <Ellipse.Fill>
                <RadialGradientBrush>
                    <GradientStop Color="#CA2C8DDE" Offset="0.634"/>
                    <GradientStop Color="#39FFFFFF" Offset="1"/>
                    <GradientStop Color="#CA2C64DE" Offset="0.33"/>
                    <GradientStop Color="#B56A8FDE" Offset="0.062"/>
                </RadialGradientBrush>
            </Ellipse.Fill>
        </Ellipse>

Figure 7 shows my finished UserControl.

image

Figure 7: Finished UserControl.

The Grow Animation

Now that I’ve finished the ellipse I need to design the Grow/Shrink animation.  I’ll use Scale Transform to change the size of the ellipse.  To be more precise I am animating the shape’s ScaleX and ScaleY properties.  I want the dot to grow from zero scale to full scale in roughly two seconds.  Once the dot is full size, I want it to hesitate for a short time and then quickly disappear.  Figure 8 shows my resulting timeline after experimenting in Blend.

Do you see the two keyframes at 2.0 and 2.5 seconds?  These two keyframes make the animation appear to hesitate before it shrinks from sight.  To recap: the dot grows in size for two seconds, stays at that size for 0.5 seconds and then scales back to zero in 0.5 seconds.

image

Figure 8: The four keyframes

Video 5 shows what my animation looks like.

Video 5: Grow animation.

Adding a Custom BeginTime Property

Now I want to show you how to control the start time of my BlueDot animation. Currently the animation starts on the Control Loaded event.  The finished circular pattern will consist of eight BlueDot controls.  If I use the control as it is currently implemented each BlueDot’s grow animation will start simultaneously. Instead I want to stagger the start time of each animation.  Adding a BeginTime dependency property to the BlueDot control allows the host container, in this example the page, to choose the start time.

I need to know the Key value for the BlueDot control.  A quick look in the XAML files shows that mine is named GrowStoryboard.  The Key value is necessary when I call FindResource to get a reference to the storyboard.

XAML

<!-- This is the main Storyboard for the grow/fade animation. -->
    <Storyboard x:Key="GrowStoryboard">

In the code behind I get a reference to the storyboard in the constructor.  Then I create the dependency property and setup a PropertyChangedCallback method.

Code Behind

public partial classBlueDot: UserControl

{

    privateStoryboard_sb;

    publicBlueDot()

    {

        InitializeComponent();

        // find the resource declared in the XAML file

        _sb = FindResource("GrowStoryboard") as Storyboard;
    }

    /// <summary>
    /// BeginTime Dependency Property
    /// </summary>
    public static readonly DependencyProperty BeginTimeProperty =
            DependencyProperty.Register("BeginTime", typeof(TimeSpan), 
                                         typeof(BlueDot),
                    new FrameworkPropertyMetadata((TimeSpan)TimeSpan.FromMilliseconds(0),
                    new PropertyChangedCallback(OnBeginTimeChanged)));

    /// <summary>
    /// Gets or sets the BeginTime property.  This dependency property
    /// indicates what time the animation should start.
    /// </summary>
    public TimeSpan BeginTime
    {
        get { return (TimeSpan)GetValue(BeginTimeProperty); }
        set { SetValue(BeginTimeProperty, value); }
    }

    /// <summary>
    /// Handles changes to the BeginTime property.
    /// </summary>
    private static void OnBeginTimeChanged(DependencyObject d, 
                         DependencyPropertyChangedEventArgs e)
    {
        ((BlueDot)d).OnBeginTimeChanged(e);
    }

    /// <summary>
    /// Provides derived classes an opportunity to handle changes to the BeginTime property.
    /// </summary>
    protected virtual void OnBeginTimeChanged(DependencyPropertyChangedEventArgs e)
    {
        _sb.BeginTime = (TimeSpan)e.NewValue;
    }
}

UserControls on the ToolBox in Expression Blend

Once you have compiled a project in Expression Blend (F5) any UserControls in the project are added to the Assets library.  To add the new BlueDot control to the ToolBox:

 

1.

Click the Asset Library button on the ToolBox.

image

2.

Click the Custom Controls button.

Choose the BlueDot control from the list of controls.

image
3. The selected control is added to the ToolBox. image

 

Putting it All Together

The final touch it to create the circular pattern with the new BlueDot control.  I just showed how to do this in the previous demo so the steps should be fresh in your mind.

  1. Add the BlueDot control to a Window/Page.
  2. Move the CenterPoint to a new location.
  3. Make seven copies of the BlueDot control.
  4. For each copy, change the RotationTransform angle to a multiple of 45

    (0, 45, 90, 135, 180, 225, 270, 315).

  5. Add a 360-degree rotation animation to all the shapes.

Using the BeginTime property

It’s time to set the BlueDot.BeginTime property for each of the eight user controls. I can set this in the XAML but for this project I decided to use the Blend Property Pane.

1.

Choose one of the BlueDot user controls in the Artboard.  For this example I picked the one at the 3 o’clock position.

Note: the animation will be running while viewing the items in Blend.

image

2.

In the Property pane search box type: "Begin".  The Property pane should narrow the results and only show the BeginTime property.

Set the BeginTime value to 400 milliseconds (00:00:00.4000000).

image

3. Continue setting the BeginTime property on the other BlueDots.  I choose to stagger each one 200 milliseconds from its neighbors.  

You can see the resulting XAML.

<CircularAnimations_Examples:BlueDot  Width="40"
                                      Height="40"
                                      RenderTransformOrigin="0.508,2"
                                      BeginTime='00:00:00.4'>
     <CircularAnimations_Examples:BlueDot.RenderTransform>
       <TransformGroup>
         <ScaleTransform ScaleX="1"
                         ScaleY="1" />
         <SkewTransform AngleX="0"
                        AngleY="0" />
         <RotateTransform Angle="90" />
         <TranslateTransform X="0"
                             Y="0" />
       </TransformGroup>
     </CircularAnimations_Examples:BlueDot.RenderTransform>
   </CircularAnimations_Examples:BlueDot>

Now it’s time to see the results of all this work (Video 6).  I think you’ll agree that it looks very similar to the official Silverlight animation.

Video 6: Silverlight animation recreated.

What’s Next?

That’s all I have for you.  Now you get to show your creative side.  What kinds of circular animations will you make?

Source Code and Sample Project

You can find the examples from Part 1 and Part 2 of this article in the CircularAnimation project available on the MSDN Code Gallery site.

[Source code for article is available on CodeGallery]

One Response to “Arranging Shapes in a Circle with Expression Blend – Part 2”

  1. [...] part two of this article I will show you how to arrange elements evenly about the perimeter of a circle and how to recreate [...]