How to: Animate an Object Along a Path (Matrix Animation with Offset Accumulation)

This example shows how to use the MatrixAnimationUsingPath class to animate an object along a path and have that animation accumulate its offset values as it repeats.

Example

The following example uses the MatrixAnimationUsingPath object to animate the Matrix property of a MatrixTransform applied to a button. As a result, a button moves along a curved path.

In addition, the example sets the IsOffsetCumulative property to true, which causes the offset of the animated matrix to accumulate as the animation repeats. Because the offset accumulates, the button moves farther across the screen when the animation repeats, rather than resetting to the starting position.

<Page 
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Margin="20"
  xmlns:PresentationOptions="https://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">
  
  <Canvas Width="400" Height="400">
  

    <!-- The Button that is animated across the screen by animating
         the MatrixTransform applied to the button. -->
    <Button MinWidth="100" Content="A Button">
      <Button.RenderTransform>
        <MatrixTransform x:Name="myMatrixTransform">
          <MatrixTransform.Matrix >
            <Matrix />
          </MatrixTransform.Matrix>
        </MatrixTransform>
      </Button.RenderTransform>
      <Button.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
          <BeginStoryboard Name="Foo">
            <Storyboard>
              <MatrixAnimationUsingPath
              Storyboard.TargetName="myMatrixTransform"
              Storyboard.TargetProperty="Matrix"
              IsOffsetCumulative="True"
              Duration="0:0:5" 
              RepeatBehavior="2x">
                <MatrixAnimationUsingPath.PathGeometry>
                  <PathGeometry 
                    Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100" 
                    PresentationOptions:Freeze="True" />
                </MatrixAnimationUsingPath.PathGeometry>
              </MatrixAnimationUsingPath>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Button.Triggers>
      
    </Button>   
  </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
{

    /// <summary>
    /// Shows how to use the MatrixAnimationUsingPath.IsOffsetCumulative
    /// property to make a MatrixAnimatioinUsingPath accumulate
    /// its values when it repeats.
    /// </summary>
    public class MatrixAnimationUsingPathExampleOffsetCumulative : Page
    {

        public MatrixAnimationUsingPathExampleOffsetCumulative()
        {
            this.Margin = new Thickness(20);

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

            // Create a button.
            Button aButton = new Button();
            aButton.MinWidth = 100;
            aButton.Content = "A Button";

            // Create a MatrixTransform. This transform
            // will be used to move the button.
            MatrixTransform buttonMatrixTransform = new MatrixTransform();
            aButton.RenderTransform = buttonMatrixTransform;

            // Register the transform's name with the page
            // so that it can be targeted by a Storyboard.
            this.RegisterName("ButtonMatrixTransform", buttonMatrixTransform);

            // Create a Canvas to contain the button
            // and add it to the page.
            // Although this example uses a Canvas,
            // any type of panel will work.
            Canvas mainPanel = new Canvas();
            mainPanel.Width = 400;
            mainPanel.Height = 400;
            mainPanel.Children.Add(aButton);
            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 MatrixAnimationUsingPath to move the
            // button along the path by animating
            // its MatrixTransform.
            MatrixAnimationUsingPath matrixAnimation =
                new MatrixAnimationUsingPath();
            matrixAnimation.PathGeometry = animationPath;

            // Set IsOffsetCumulative to true so that the animation
            // values accumulate when its repeats. 
            matrixAnimation.IsOffsetCumulative = true;
            matrixAnimation.Duration = TimeSpan.FromSeconds(5);
            matrixAnimation.RepeatBehavior = new RepeatBehavior(2);

            // Set the animation to target the Matrix property
            // of the MatrixTransform named "ButtonMatrixTransform".
            Storyboard.SetTargetName(matrixAnimation, "ButtonMatrixTransform");
            Storyboard.SetTargetProperty(matrixAnimation, 
                new PropertyPath(MatrixTransform.MatrixProperty));
      
            // Create a Storyboard to contain and apply the animation.
            Storyboard pathAnimationStoryboard = new Storyboard();
            pathAnimationStoryboard.Children.Add(matrixAnimation);

            // Start the animation when the button is clicked.
            aButton.Click += delegate(object sender, RoutedEventArgs e)
            {
                // Start the storyboard.
                pathAnimationStoryboard.Begin(this);
            };

        }  
    }
}

Note that, although the IsOffsetCumulative property causes offset values to accumulate over repetitions, it doesn't cause rotation values to accumulate. To make rotation values accumulate, set the animation's DoesRotateWithTangent and IsAngleCumulative properties to true.

For the complete sample, see Path Animation Sample. For an example showing how to animate a Matrix value along a path without offset accumulation, see How to: Animate an Object Along a Path (Matrix Animation).

See Also

Tasks

How to: Animate an Object Along a Path (Matrix Animation)
How to: Rotate an Object by Using a Geometric Path (Matrix Animation)
How to: Animate an Object Along a Path (Point Animation)
How to: Animate an Object Along a Path (Double Animation)
How to: Rotate an Object by Using a Geometric Path

Concepts

Animation Overview

Other Resources

Path Animation Sample
Path Animation How-to Topics