How to: Rotate an Object by Using a Geometric Path

This example shows how to rotate (pivot) an object along a geometric path that is defined by a PathGeometry object.

Example

The following example uses three DoubleAnimationUsingPath objects to move a rectangle along a geometric path.

  • The first DoubleAnimationUsingPath animates a RotateTransform that is applied to the rectangle. The animation generates angle values. It makes the rectangle rotate (pivot) along the contours of the path.

  • The other two objects animate the X and Y values of a TranslateTransform that is applied to the rectangle. They make the rectangle move horizontally and vertically along the path.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">
  <Page.Resources>
    
    <!-- This is the geometry creates the animation path. Because 
         this example uses it multiple times, it's declared as a resource and
         frozen to improve performance. -->
    <PathGeometry x:Key="AnimationPath"
      Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100"
      PresentationOptions:Freeze="True" />
  </Page.Resources>
  
  <Canvas Width="400" Height="400">
  

  
    <!-- The object to animate. -->
    <Rectangle   
      Width="30" Height="30" Fill="Blue">
      <Rectangle.RenderTransform>
        <TransformGroup>
          <RotateTransform x:Name="AnimatedRotateTransform" />
          <TranslateTransform x:Name="AnimatedTranslateTransform"  />
        </TransformGroup>        
      </Rectangle.RenderTransform>   
  
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Path.Loaded">
          <BeginStoryboard>
            <Storyboard RepeatBehavior="Forever" AutoReverse="True" >

              <!-- Generates angle values (in degrees) from
                   the path. This animation is used to
                   rotate the rectangle. -->
              <DoubleAnimationUsingPath
                Storyboard.TargetName="AnimatedRotateTransform"
                Storyboard.TargetProperty="Angle"
                PathGeometry="{StaticResource AnimationPath}"
                Source="Angle"
                Duration="0:0:5"  />

              <!-- Generates horizontal offset values from
                   the path. This animation is used to 
                   animate the rectangle horizontally. -->
              <DoubleAnimationUsingPath
                Storyboard.TargetName="AnimatedTranslateTransform"
                Storyboard.TargetProperty="X"
                PathGeometry="{StaticResource AnimationPath}"
                Source="X" 
                Duration="0:0:5"  />

              <!-- Generates vertical offset values from
                   the path. This animation is used to move
                   the rectangle vertically. -->
              <DoubleAnimationUsingPath
                Storyboard.TargetName="AnimatedTranslateTransform"
                Storyboard.TargetProperty="Y"
                PathGeometry="{StaticResource AnimationPath}"
                Source="Y" 
                Duration="0:0:5"  />
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers>
    </Rectangle>
  </Canvas>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;


namespace SDKSample
{


    public class RotateAnimationUsingPathExample : Page
    {

        public RotateAnimationUsingPathExample()
        {

            // Create a NameScope for the page so that
            // we can use Storyboards.
            NameScope.SetNameScope(this, new NameScope());

            // Create a rectangle.
            Rectangle aRectangle = new Rectangle();
            aRectangle.Width = 30;
            aRectangle.Height = 30;
            aRectangle.Fill = Brushes.Blue;

            // Create some transforms. These transforms
            // will be used to move and rotate the rectangle.
            RotateTransform animatedRotateTransform = 
                new RotateTransform();
            TranslateTransform animatedTranslateTransform = 
                new TranslateTransform();

            // Register the transforms' names with the page
            // so that they can be targeted by a Storyboard.
            this.RegisterName("AnimatedRotateTransform", animatedRotateTransform);
            this.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform);    

            // Create a TransformGroup to contain the transforms
            // and apply the TransformGroup to the rectangle.
            TransformGroup tGroup = new TransformGroup();
            tGroup.Children.Add(animatedRotateTransform);
            tGroup.Children.Add(animatedTranslateTransform);
            aRectangle.RenderTransform = tGroup;

            // Create a Canvas to contain the rectangle
            // and add it to the page.
            Canvas mainPanel = new Canvas();
            mainPanel.Width = 400;
            mainPanel.Height = 400;
            mainPanel.Children.Add(aRectangle);
            this.Content = mainPanel;

            // Create the animation path.
            PathGeometry animationPath = new PathGeometry();
            PathFigure pFigure = new PathFigure();
            pFigure.StartPoint = new Point(10, 100);
            PolyBezierSegment pBezierSegment = new PolyBezierSegment();
            pBezierSegment.Points.Add(new Point(35, 0));
            pBezierSegment.Points.Add(new Point(135, 0));
            pBezierSegment.Points.Add(new Point(160, 100));
            pBezierSegment.Points.Add(new Point(180, 190));
            pBezierSegment.Points.Add(new Point(285, 200));
            pBezierSegment.Points.Add(new Point(310, 100));
            pFigure.Segments.Add(pBezierSegment);
            animationPath.Figures.Add(pFigure);

            // Freeze the PathGeometry for performance benefits.
            animationPath.Freeze();

            // Create a DoubleAnimationUsingPath to rotate the
            // rectangle with the path by animating 
            // its RotateTransform.
            DoubleAnimationUsingPath angleAnimation = 
                new DoubleAnimationUsingPath();
            angleAnimation.PathGeometry = animationPath;
            angleAnimation.Duration = TimeSpan.FromSeconds(5);

            // Set the Source property to Angle. This makes
            // the animation generate angle values from
            // the path information. 
            angleAnimation.Source = PathAnimationSource.Angle;

            // Set the animation to target the Angle property
            // of the RotateTransform named "AnimatedRotateTransform".
            Storyboard.SetTargetName(angleAnimation, "AnimatedRotateTransform");
            Storyboard.SetTargetProperty(angleAnimation, 
                new PropertyPath(RotateTransform.AngleProperty));

            // Create a DoubleAnimationUsingPath to move the
            // rectangle horizontally along the path by animating 
            // its TranslateTransform.
            DoubleAnimationUsingPath translateXAnimation =
                new DoubleAnimationUsingPath();
            translateXAnimation.PathGeometry = animationPath;
            translateXAnimation.Duration = TimeSpan.FromSeconds(5);

            // Set the Source property to X. This makes
            // the animation generate horizontal offset values from
            // the path information. 
            translateXAnimation.Source = PathAnimationSource.X;

            // Set the animation to target the X property
            // of the TranslateTransform named "AnimatedTranslateTransform".
            Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform");
            Storyboard.SetTargetProperty(translateXAnimation,
                new PropertyPath(TranslateTransform.XProperty));

            // Create a DoubleAnimationUsingPath to move the
            // rectangle vertically along the path by animating 
            // its TranslateTransform.
            DoubleAnimationUsingPath translateYAnimation =
                new DoubleAnimationUsingPath();
            translateYAnimation.PathGeometry = animationPath;
            translateYAnimation.Duration = TimeSpan.FromSeconds(5);

            // Set the Source property to Y. This makes
            // the animation generate vertical offset values from
            // the path information. 
            translateYAnimation.Source = PathAnimationSource.Y;

            // Set the animation to target the Y property
            // of the TranslateTransform named "AnimatedTranslateTransform".
            Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform");
            Storyboard.SetTargetProperty(translateYAnimation,
                new PropertyPath(TranslateTransform.YProperty)); 
      
            // Create a Storyboard to contain and apply the animations.
            Storyboard pathAnimationStoryboard = new Storyboard();
            pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
            pathAnimationStoryboard.AutoReverse = true;
            pathAnimationStoryboard.Children.Add(angleAnimation);
            pathAnimationStoryboard.Children.Add(translateXAnimation);
            pathAnimationStoryboard.Children.Add(translateYAnimation);

            // Start the animations when the rectangle is loaded.
            aRectangle.Loaded += delegate(object sender, RoutedEventArgs e)
            {
                // Start the storyboard.
                pathAnimationStoryboard.Begin(this);
            };

        }
    
    }

}

Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Imports System.Windows.Navigation
Imports System.Windows.Shapes


Namespace SDKSample


	Public Class RotateAnimationUsingPathExample
		Inherits Page

		Public Sub New()

			' Create a NameScope for the page so that
			' we can use Storyboards.
			NameScope.SetNameScope(Me, New NameScope())

			' Create a rectangle.
			Dim aRectangle As New Rectangle()
			aRectangle.Width = 30
			aRectangle.Height = 30
			aRectangle.Fill = Brushes.Blue

			' Create some transforms. These transforms
			' will be used to move and rotate the rectangle.
			Dim animatedRotateTransform As New RotateTransform()
			Dim animatedTranslateTransform As New TranslateTransform()

			' Register the transforms' names with the page
			' so that they can be targeted by a Storyboard.
			Me.RegisterName("AnimatedRotateTransform", animatedRotateTransform)
			Me.RegisterName("AnimatedTranslateTransform", animatedTranslateTransform)

			' Create a TransformGroup to contain the transforms
			' and apply the TransformGroup to the rectangle.
			Dim tGroup As New TransformGroup()
			tGroup.Children.Add(animatedRotateTransform)
			tGroup.Children.Add(animatedTranslateTransform)
			aRectangle.RenderTransform = tGroup

			' Create a Canvas to contain the rectangle
			' and add it to the page.
			Dim mainPanel As New Canvas()
			mainPanel.Width = 400
			mainPanel.Height = 400
			mainPanel.Children.Add(aRectangle)
			Me.Content = mainPanel

			' Create the animation path.
			Dim animationPath As New PathGeometry()
			Dim pFigure As New PathFigure()
			pFigure.StartPoint = New Point(10, 100)
			Dim pBezierSegment As New PolyBezierSegment()
			pBezierSegment.Points.Add(New Point(35, 0))
			pBezierSegment.Points.Add(New Point(135, 0))
			pBezierSegment.Points.Add(New Point(160, 100))
			pBezierSegment.Points.Add(New Point(180, 190))
			pBezierSegment.Points.Add(New Point(285, 200))
			pBezierSegment.Points.Add(New Point(310, 100))
			pFigure.Segments.Add(pBezierSegment)
			animationPath.Figures.Add(pFigure)

			' Freeze the PathGeometry for performance benefits.
			animationPath.Freeze()

			' Create a DoubleAnimationUsingPath to rotate the
			' rectangle with the path by animating 
			' its RotateTransform.
			Dim angleAnimation As New DoubleAnimationUsingPath()
			angleAnimation.PathGeometry = animationPath
			angleAnimation.Duration = TimeSpan.FromSeconds(5)

			' Set the Source property to Angle. This makes
			' the animation generate angle values from
			' the path information. 
			angleAnimation.Source = PathAnimationSource.Angle

			' Set the animation to target the Angle property
			' of the RotateTransform named "AnimatedRotateTransform".
			Storyboard.SetTargetName(angleAnimation, "AnimatedRotateTransform")
			Storyboard.SetTargetProperty(angleAnimation, New PropertyPath(RotateTransform.AngleProperty))

			' Create a DoubleAnimationUsingPath to move the
			' rectangle horizontally along the path by animating 
			' its TranslateTransform.
			Dim translateXAnimation As New DoubleAnimationUsingPath()
			translateXAnimation.PathGeometry = animationPath
			translateXAnimation.Duration = TimeSpan.FromSeconds(5)

			' Set the Source property to X. This makes
			' the animation generate horizontal offset values from
			' the path information. 
			translateXAnimation.Source = PathAnimationSource.X

			' Set the animation to target the X property
			' of the TranslateTransform named "AnimatedTranslateTransform".
			Storyboard.SetTargetName(translateXAnimation, "AnimatedTranslateTransform")
			Storyboard.SetTargetProperty(translateXAnimation, New PropertyPath(TranslateTransform.XProperty))

			' Create a DoubleAnimationUsingPath to move the
			' rectangle vertically along the path by animating 
			' its TranslateTransform.
			Dim translateYAnimation As New DoubleAnimationUsingPath()
			translateYAnimation.PathGeometry = animationPath
			translateYAnimation.Duration = TimeSpan.FromSeconds(5)

			' Set the Source property to Y. This makes
			' the animation generate vertical offset values from
			' the path information. 
			translateYAnimation.Source = PathAnimationSource.Y

			' Set the animation to target the Y property
			' of the TranslateTransform named "AnimatedTranslateTransform".
			Storyboard.SetTargetName(translateYAnimation, "AnimatedTranslateTransform")
			Storyboard.SetTargetProperty(translateYAnimation, New PropertyPath(TranslateTransform.YProperty))

			' Create a Storyboard to contain and apply the animations.
			Dim pathAnimationStoryboard As New Storyboard()
			pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever
			pathAnimationStoryboard.AutoReverse = True
			pathAnimationStoryboard.Children.Add(angleAnimation)
			pathAnimationStoryboard.Children.Add(translateXAnimation)
			pathAnimationStoryboard.Children.Add(translateYAnimation)

			' Start the animations when the rectangle is loaded.
			AddHandler aRectangle.Loaded, Sub(sender As Object, e As RoutedEventArgs) pathAnimationStoryboard.Begin(Me)

		End Sub

	End Class

End Namespace

Another way to rotate an object by using a geometric path is to use a MatrixAnimationUsingPath object and set its DoesRotateWithTangent property to true. For more information and an example, see Rotate an Object by Using a Geometric Path (Matrix Animation).

For the complete sample, see Path Animation Sample.

See Also

Animation Overview
Path Animation Sample
Path Animation How-to Topics