Many of the enhancements to the C1Chart control in 2012 v3 were to make development easier. Animation is one of those features. You’ve always been able to apply animations to the plot elements, but now with the new animation API it got a lot easier. This blog post walks through creating load animations in XAML.

When we design our XAML controls we try to leave them as flexible as possible while adding as many features as possible. That can be a tough challenge for us as control developers, but it’s what we do best. So we didn’t want to just give you a single enumerated property like “Animation” with a dozen or so options to choose from. That would leave you limited in what you could do easily. So we meet you half-way with a single PlotElementAnimation class that has two properties: Storyboard and SymbolStyle. You can create any combination of a storyboard and style to customize your animation. Then you can assign an instance of PlotElementAnimation to the new LoadAnimation property on the chart’s Data object.

Let’s walk through an example backward to see how this works.

Creating a Fade-in Animation


Here I have a chart with a load animation that will change the opacity of plot elements to create a fade-in effect.


<c1:C1Chart x:Name="c1Chart1" Palette="Office">
<c1:C1Chart.Data>
<c1:ChartData>
<c1:DataSeries Label="s1" Values="1 2 3 4 5" />
<c1:ChartData.LoadAnimation>
<c1:PlotElementAnimation Storyboard="{StaticResource sbOpacity}"
SymbolStyle="{StaticResource styleOpacity}"/>
</c1:ChartData.LoadAnimation>
</c1:ChartData>
</c1:C1Chart.Data>
</c1:C1Chart>


Notice to apply an animation we create a PlotElementAnimation with a Storyboard and SymbolStyle that define the animation. Now let’s see how to create these resources.


<Style TargetType="c1:PlotElement" x:Key="styleOpacity">
<Setter Property="Opacity" Value="0" />
</Style>
<Storyboard x:Key="sbOpacity">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="00:00:01"
From="0" To="1"
c1:PlotElementAnimation.IndexDelay="0.5"/>
</Storyboard>


The Style and Storyboard here are typical XAML resources that everyone is familiar with. Defining our own Storyboard gives us the flexibility to create any animation possible within the XAML platform, yet with a simple, standard protocol. Also note the Style resource applies to the c1:PlotElement type. This is always the case for any kind of animation you create. The key thing is to link the TargetProperty from the Storyboard to some property setter in our Style. Next we’ll see how to use Styles and Storyboards to create more types of animation.


Creating a Scaling Animation


A scaling animation makes the plot elements grow or scale in size. With scaling animations there are a couple other properties we can set on our Style and Storyboard, such as EasingFunction and RenderTransformOrigin.


<Style TargetType="c1:PlotElement" x:Key="styleScale">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0" ScaleY="0" />
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5" />
</Style>
<Storyboard x:Key="sbScale">
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).ScaleX" Duration="00:00:01" From="0" To="1" c1:PlotElementAnimation.IndexDelay="0.5">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).ScaleY" Duration="00:00:00" From="0" To="1">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>


Notice here I set the ScaleY duration to 00:00:00, so theoretically I can remove it. But I left it in case you want to increase this duration in your sample. Setting one of the Scale properties to 0 duration will create a unique scaling effect as seen below.

To assign this Style and Storyboard to the C1Chart control, see the above example with fade-in animation.



The property setter for RenderTransformOrigin defines where the animation will be positioned. A value of (0.5, 0.5) means that it’s centered. Here’s a quick list of other positions you could set:

  • Center = (0.5, 0.5)

  • Bottom = (0.5, 2)

  • Top = (0.5, -2)

  • Left = (-2, 0.5)

  • Right = (2, 0.5)

  • Top Left = (2, -2)

  • Top Right = (-2, -2)

  • Bottom Left = (2, 2)

  • Bottom Right = (-2, 2)


Easing functions allow you to apply custom mathematical formulas to your animations. They are built-in to the Storyboard API so they’re very easy to configure. Each function may have additional properties like Springiness, Bounciness, Easing Mode and Amplitude so you can further customize the animation.

Examples of Easing Functions:

  • BackEase

  • BounceEase

  • CircleEase

  • CubicEase

  • ElasticEase

  • ExponentialEase

  • PowerEase

  • QuadraticEase

  • QuarticEase

  • SineEase


Creating a Rotation Animation


Rotation animations are similar to scaling animations - they just use a RotateTransform rather than a ScaleTransform (go figure). And like scaling animations you can customize the origin (RenderTransformOrigin) as well as the easing function.


<Style TargetType="c1:PlotElement" x:Key="styleRotate">
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="180" />
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5" />
</Style>
<Storyboard x:Key="sbRotate">
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).Angle" Duration="00:00:01" To="1" c1:PlotElementAnimation.IndexDelay="0.5">
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseIn" Amplitude="5" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>



Index Delay


If you apply any of the above examples you will notice that all plot elements animate one at a time. This is due to the attached IndexDelay property. This allows you to set a delay time between each point. This creates an escalating animation effect and is great for column, bar, pie and scatter charts (it has no real effect on Area or Line charts).

For an example, let’s look at the scaling animation again. This time we set the attached IndexDelay property on each Animation object where we want delay.


<Style TargetType="c1:PlotElement" x:Key="styleScale">
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="0" ScaleY="0" />
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5" />
</Style>
<Storyboard x:Key="sbScale">
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).ScaleX" Duration="00:00:01" From="0" To="1"
c1:PlotElementAnimation.IndexDelay="0.5">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).ScaleY" Duration="00:00:00" From="0" To="1">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>

Composite Animations using TransformGroup


You can combine any of the types of animations described so far. The trick is to use a TransformGroup within your Style resource. This is only necessary if you are combining Scale and Rotate. This example combines opacity, scale and rotate into one storyboard.


<Style TargetType="c1:PlotElement" x:Key="styleComposite">
<Setter Property="RenderTransform">
<Setter.Value>
<TransformGroup>
<ScaleTransform ScaleX="0" ScaleY="0" />
<RotateTransform Angle="180" />
</TransformGroup>
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5" />
<Setter Property="Opacity" Value="0" />
</Style>
<Storyboard x:Key="sbComposite">
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="00:00:01" From="0" To="1"
c1:PlotElementAnimation.IndexDelay="1"/>
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(TransformGroup.Children)[0].ScaleX" Duration="00:00:01" From="0" To="1"
c1:PlotElementAnimation.IndexDelay="1">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(TransformGroup.Children)[0].ScaleY" Duration="00:00:01" From="0" To="1">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Storyboard.TargetProperty="(RenderTransform).(TransformGroup.Children)[1].Angle" Duration="00:00:01" To="1"
c1:PlotElementAnimation.IndexDelay="1">
<DoubleAnimation.EasingFunction>
<BackEase />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>




As you can see the animation API is simple enough to implement, yet left flexible enough that you really have the entire WPF, Silverlight, Phone or WinRT animation capabilities available to you. You can download a sample in WPF. To see how to apply these types of animations entirely in code I suggest taking a look at the chart samples that we install in the 2012 v3 setup, or by searching here.