Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

# Silverlight Animation

### Transforms

As you've already learned, Silverlight animations work by modifying the value of a property. Elements have several properties that can be usefully changed. For example, you can use Canvas.Left and Canvas.Top to move an element around. Or, you can alter the Opacity setting to make an element fade into or out of view. However, it's not immediately clear how you can perform more exciting alterations, like rotations.

The secret is "transforms." A transform is an object that alters the way a shape or other element is drawn by shifting the coordinate system it uses. You can use transforms to stretch, rotate, skew, and otherwise manipulate the shapes, images, and text in your Silverlight user interface. Transforms are useful for getting the right shape you want, but they're even more interesting when you're animating. By animating a property in a transform, you can rotate a shape, move it from one place to another, or warp it dynamically.

Table 2 lists the transforms that are supported in Silverlight.

 TranslateTransform Displaces your coordinate system by some amount. This transform is useful if you want to draw the same shape in different places. X,Y RotateTransform Rotates your coordinate system. The shapes you draw normally are turned around a center point you choose. Angle, CenterX, CenterY ScaleTransform Scales your coordinate system up or down so that your shapes are drawn smaller or larger. You can apply different degrees of scaling in the X and Y dimensions, thereby stretching or compressing your shape. ScaleX, ScaleY, CenterX, CenterY SkewTransform Warps your coordinate system by slanting it a number of degrees. For example, if you draw a square, it becomes a parallelogram. AngleX, AngleY, CenterX, CenterY MatrixTransform Modifies your coordinate system using matrix multiplication with the matrix you supply. This is the most complex option -- it requires some mathematical skill. Matrix TransformGroup Combines multiple transforms so they can all be applied at once. The order in which you apply transformations is important -- it affects the final result. For example, rotating a shape (with RotateTransform) and then moving it (with TranslateTransform) sends the shape off in a different direction than if you move it and then rotate it. N/A
Table 2: Transform Classes

Technically, all transforms use matrix math to alter the coordinates of your shape. However, using prebuilt transforms such as TranslateTransform, RotateTransform, ScaleTransform, and SkewTransform is far simpler than using the MatrixTransform and trying to work out the right matrix for the operation you want to perform. When you perform a series of transforms with TransformGroup, Silverlight fuses your transforms together into a single MatrixTransform, ensuring optimal performance.

#### Using a Transform

To transform an element, you set its RenderTransform property with the transform object you want to use. Depending on the transform object you're using, you'll need to fill in different properties to configure it, as detailed in Table 2.

For example, if you're rotating a shape, you need to use the RotateTransform and supply the angle in degrees. Here's an example that rotates a square clockwise by 25 degrees:

```<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" />
</Rectangle.RenderTransform>
</Rectangle>
```

When you rotate a shape in this way, you rotate it about the shape's origin (the top-left corner). If you want to rotate a shape around a different point, you can use the handy RenderTransformOrigin property. This property sets the center point using a proportional coordinate system that stretches from 0 to 1 in both dimensions. In other words, the point (0, 0) is designated as the top-left corner, and (1, 1) is the bottom-right corner. (If the shape region isn't square, the coordinate system is stretched accordingly.)

With the help of the RenderTransformOrigin property, you can rotate any shape around its center point using markup like this:

```<Rectangle Width="80" Height="10" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100"    RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="25" />
</Rectangle.RenderTransform>
</Rectangle>
```

#### Animating a Transform

To use a transform in animation, the first step is to define the transform. (An animation can change an existing transform but not create a new one.) For example, imagine you want to allow a rectangle to rotate. This requires RotateTransform:

```<Rectangle x:Name="rect" Width="80" Height="50" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<RotateTransform></RotateTransform>
</Rectangle.RenderTransform>
</Rectangle>
```

Now here's a storyboard that makes the rectangle rotate when the mouse moves over it. It uses the target property (UIElement.RenderTransform).Angle -- in other words, it reads the RenderTransform property of the Rectangle and modifies the Angle property of the RotateTransform object that's defined there. The fact that the RenderTransform property can hold a variety of different transform objects, each with different properties, doesn't cause a problem. As long as you're using a transform that has an angle property, this trigger will work.

```<Rectangle x:Name="rect" Width="80" Height="50" Stroke="Blue" Fill="Yellow"
Canvas.Left="100" Canvas.Top="100" RenderTransformOrigin="0.5,0.5"
MouseEnter="rect_Enter">
<Rectangle.RenderTransform>
<RotateTransform></RotateTransform>
</Rectangle.RenderTransform>
<Rectangle.Resources>
<Storyboard x:Name="rotateStoryboard">
<DoubleAnimation
Storyboard.TargetName="rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).Angle"
To="360" Duration="0:0:0.8" RepeatBehavior="Forever"></DoubleAnimation>
</Storyboard>
</Rectangle.Resources>
</Rectangle>
```

Finally, an event handler starts the storyboard:

```private void rect_Enter(object o, EventArgs e)
{
rotateStoryboard.Begin();
}
```

The rectangle rotates one revolution every 0.8 seconds and continues rotating perpetually. While the rectangle is rotating, it's still completely usable -- for example, it still raises the MouseLeftButtonDown event if you click it.

To stop the rotation, you can use a second trigger that responds to the MouseLeave event. At this point, you could call the Storyboard.Stop() method, but this will cause the button to jump back to its original orientation in one step. A better approach is to start a second animation that replaces the first. Here's how the second animation is defined:

```<Storyboard x:Name="revertStoryboard">
<DoubleAnimation
Storyboard.TargetName="rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).Angle"
To="0" Duration="0:0:0.2"></DoubleAnimation>
</Storyboard>
```

This animation seamlessly rotates the rectangle back to its original orientation in a snappy 0.2 seconds. You can place this storyboard in the same Rectangle.Resources collection as the first animation.

All you need to do is attach an event handler to the Rectangle.MouseLeave event that runs the storyboard:

```private void rect_Leave(object o, EventArgs e)
{
revertStoryboard.Begin();
}
```

### More Insights

 To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.