Charles Petzold

XAML Spiral Animation

October 21, 2006
Roscoe, NY for the weekend

I've been wondering for awhile how to define a XAML animation to make an object move in a spiral. I tried one approach, and couldn't quite get it, so I tried another approach similar to the winding-down pendulum example I did over the summer, and that worked.

The technique involves defining a compound transform on an invisible element. (FrameworkElement itself works just fine for this purpose). The visible element — the one being animated — then has bindings to select elements of the resultant compound matrix. For the spiral, the compound transform on FrameworkElement consists of a rotation and scaling. The rotation goes from 0 to 360 degress, repeated forever, while the scaling is much slower, and goes from 0 to 240, and then back again, repeated forever.

Normally, such a compound transform would cause an object to both rotate and increase in size. However, The first two elements of the matrix are x and y coordinates for an object moving in a spiral. The visible element — a little red ball — binds to these two elements of the matrix to position itself on a Canvas. Here's the XAML file:


The entire cycle — spiraling out to a radius of 2.5" and then spiraling back in — takes 8 minutes. You can speed it up by putting a SpeedRatio attribute on the Storyboard element.

I then came up with a second approach that uses transforms in a more conventional manner, but which requires three animations rather than two. The first animation rotates the ball from 0 to 360 degress, repeated forever. Because the ball is sitting at the point (0, 0), normally this rotation wouldn't have any visual effect. But a second animation moves the center of rotation from (0, 0) to (240, 0). That means the ball's rotations keep getting larger and larger, but the center of rotation moves down the x-axis. A third animation corrects for that by moving the Canvas.Left property of the ball from 0 to -240. Here's the second XAML file:


My original approach — the one I couldn't quite get working right — involved a single animation of type MatrixAnimationUsingPath where the PathGeometry defined one cycle of the spiral, and it accumulated with every repetition.