Search code examples
wpfanimationcode-behind

How to Move an Ellipse Along a Path in WPF Code-Behind


I'm trying to move an ellipse along a simple PathGeometry in code-behind. The ellipse shows up. The path shows up. Nothing moves. What am I missing? Thanks!

Here's what I have. SchematicDiagram is a Canvas. sData contains a Path. Code is in VB.

                    OrPath = New Path
                    OrPath.Stroke = HGLBrush
                    OrPath.StrokeThickness = 1
                    OrPath.Data = Geometry.Parse(sData)

                    'Add to PathGeometry named flowPathGeometry
                    FlowPathGeometry = New PathGeometry
                    FlowPathGeometry.AddGeometry(OrPath.Data)
                    FlowPathGeometry.Freeze()

                    SchematicDiagram.Children.Add(OrPath)

                    'Now animate ------------------------------------------------------

                    'Create the Ellipse to animate.

                    Dim shapeMatrixTransform As New MatrixTransform()

                    Dim newellipse As New Ellipse
                    newellipse.Name = "FlowPathCircle"
                    newellipse.Fill = Brushes.Blue
                    newellipse.Height = 5
                    newellipse.Width = 5
                    newellipse.RenderTransform = shapeMatrixTransform
                    SchematicDiagram.Children.Add(newellipse)

                    NameScope.SetNameScope(SchematicDiagram, New NameScope())
                    SchematicDiagram.RegisterName("shapeMatrixTransform", newellipse)

                    'Create a MatrixAnimationUsingPath to move the shape along the path by animating its MatrixTransform
                    Dim ma As New Animation.MatrixAnimationUsingPath()
                    ma.Duration = TimeSpan.FromSeconds(5)
                    ma.RepeatBehavior = Media.Animation.RepeatBehavior.Forever
                    ma.PathGeometry = FlowPathGeometry 'the path "geometry" To use

                    'Set the animation to target the Matrix property
                    'of the MatrixTransform named "shapeMatrixTransform".
                    Media.Animation.Storyboard.SetTargetName(ma, "shapeMatrixTransform")
                    Media.Animation.Storyboard.SetTargetProperty(ma, New PropertyPath(MatrixTransform.MatrixProperty))

                    'Create a Storyboard to contain and apply the animation
                    Dim pathAnimationStoryboard As New Animation.Storyboard
                    pathAnimationStoryboard.Children.Add(ma)

                    'To Start the storyboard.
                    pathAnimationStoryboard.Begin(SchematicDiagram)

'Nothing Happens in the canvas after this code executes


Solution

  • You do not need the Storyboard. Just call

    shapeMatrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, ma)
    

    Here is a compact version of your code in C#. Besides that it does not use a Storyboard, it also uses a Path with an EllipseGeometry instead of an Ellipse, because the Path is centered while the Ellipse is top/left aligned.

    var path = new Path
    {
        Stroke = HGLBrush,
        StrokeThickness = 1,
        Data = Geometry.Parse(sData)
    };
    
    var flowPathGeometry = new PathGeometry();
    flowPathGeometry.AddGeometry(path.Data);
    flowPathGeometry.Freeze();
    
    SchematicDiagram.Children.Add(path);
    
    var shapeMatrixTransform = new MatrixTransform();
    
    var ellipse = new Path
    {
        Data = new EllipseGeometry(new Point(), 2.5, 2.5),
        Fill = Brushes.Blue,
        RenderTransform = shapeMatrixTransform
    };
    
    SchematicDiagram.Children.Add(ellipse);
    
    var animation = new MatrixAnimationUsingPath
    {
        Duration = TimeSpan.FromSeconds(5),
        RepeatBehavior = RepeatBehavior.Forever,
        PathGeometry = flowPathGeometry
    };
    
    shapeMatrixTransform.BeginAnimation(MatrixTransform.MatrixProperty, animation);
    

    For completeness it seems also worth mentioning that instead of the RenderTransform of the ellipse Path you may as well animate the Transform property of its geometry:

    var ellipse = new Path
    {
        Data = new EllipseGeometry(new Point(), 2.5, 2.5)
        {
            Transform = shapeMatrixTransform
        },
        Fill = Brushes.Blue
    };