views:

576

answers:

1

I am developing a control that is a rectangle area and will draw an ellipse in the rectangle area when a trigger occurs. This control will be able to host other controls like, textbox's, buttons, etc. so the circle will be drawn around them when triggered. I want the circle being drawn as an animation like you were circling the inner controls with a pen.

My question is whats the best way to accomplish this. I've been doing some research and I could use WPF animation or I could use GDI+ to accomplish the tasks. I am new to WPF animation so that is why I am asking the question.

+5  A: 

WPF animation makes this extremely easy. Here is the basic technique:

  1. Create your ellipse's visual appearance using whatever WPF functionality you like (Shapes, Paths, Geometries, Brushes, Drawings, Images, etc). This can be a simple ellipse or a fancy drawing created by your graphics designer, or anything in between.

  2. Apply an OpacityMask consisting of a wide elliptical dashed line with a single zero-length dash. Since the dash is zero-length the entire custom-styled ellipse will be invisible.

  3. Animate the length of the dash. As it gets longer parts of the ellipse will become opaque (so it will be visible) until it is all visible. By default your ellipse will animate smoothly from 0 to 1 but you can control and vary the rate the ellipse appears via the animation parameters, for example you could start slow at first then speed up.

Overall structure of solution

Here is the basic ControlTemplate structure:

<ControlTemplate TargetType="MyCustomControl">
  <Grid>

    <Rectangle Fill="{StaticResource EllipseVisualAppearance}">
      <Rectangle.OpacityMask>
        <VisualBrush>
          <VisualBrush.Visual>
            <Ellipse
              x:Name="opacityEllipse"
              StrokeDashArray="0 10"
              Stroke="Black" StrokeThickness="0.5"
              Width="1" Height"1" />
          </VisualBrush.Visual>
        </VisualBrush>
      </Rectangle.OpacityMask>
    </Rectangle>

    <ContentPresenter />   <!-- This presents the actual content -->

  </Grid>
</ControlTemplate>

Creating your ellipse visual

WPF is incredibly rich at expressing visuals, so the sky is the limit when it comes to what your ellipse can look like.

Draw your ellipse exactly the way you want it to appear using any WPF drawing technique. Depending on how much "artistic style" you want from the ellipse you can do a simple (and boring) stroked ellipse or anything arbitrarily fancy, such as:

  • Stroke a path that roughly an ellipse but not closed and perhaps flared out.
  • Fill a path created by a graphic designer that starts as if a paintbrush were doing it and perhaps gets wider as you go around and ends in a blob.
  • Create a vector drawing in Expression Design (or Adobe Illustrator), convert it to a XAML Drawing.
  • Create a bitmap image (note that in general bitmaps have fidelity and performance disadvantages compared to vector drawings)
  • Draw multiple Shapes on a Canvas using Expression Blend

Here is an ultimately simple ellipse:

<VisualBrush x:Key="EllipseVisualAppearance">
  <VisualBrush.Visual>
    <Ellipse StrokeThickness="0.1" Stroke="Blue" />
  </VisualBrush.Visual>
<VisualBrush>

Animating your ellipse

Again there are a huge variety of ways you can do this, depending on how you want your animation to look. For a simple 0 to 360 animation your DoubleAnimation can be as simple as:

 <DoubleAnimation
   StoryBoard.TargetName="opacityEllipse"
   StoryBoard.TargetProperty="StrokeDashArray[0]"
   From="0" To="3.1416" Duration="0:0:0.5" />

The constant 3.1416 is slightly over pi, which is the circumference of a circle of diameter 1. This means that the ellipse will be fully visible just at the end of the animation duration.

An alternative solution

StackOverflow user Simon Fox had posted an answer containing a link to this article by Charles Petzold, but his answer disappeared a few minutes later. I guess he deleted it. The Petzold code shows a simpler way to do this using PathGeometry and ArcSegment. If all you want is a simple ellipse with no frills, modeling your code on his example is probably the way to go.

Ray Burns
What other technique could I use thats not the StrokeDashArray? It appears you cannot use this because the collection element is not a dependency property.
widmayer