Search code examples
c#wpfanimationpathpoint

Animating points in a path in WPF


I am trying to animate the 3 points in my path using C# code and WPF.

I'm pretty close, although I feel the code is messy.

The one problem now is that when I animate my first of the three points, it looks like it draws a line where it travels.

Here is a link to the two states of what it is doing: https://i.sstatic.net/QWXuz.jpg

When it animates the arrow to point in the left direction, you see an extra line at the top.

public class SlideOutButton : ContentControl
{
    Path _arrowPath;
    PathSegmentCollection _pathSegments;

    public SlideOutButton(double strokeThickness = 1.0d)
    {
        _arrowPath = new Path();

        PathGeometry pathGeo = new PathGeometry();
        PathFigure figure = new PathFigure();
        _pathSegments = new PathSegmentCollection();
        _pathSegments.Add(new LineSegment(new Point(0, 0), true));
        _pathSegments.Add(new LineSegment(new Point(2, 3), true));
        _pathSegments.Add(new LineSegment(new Point(0, 6), true));
        figure.Segments = _pathSegments;
        pathGeo.Figures.Add(figure);

        _arrowPath.Data = pathGeo;
        _arrowPath.Stroke = Brushes.Black;
        _arrowPath.StrokeThickness = strokeThickness;
        _arrowPath.Stretch = Stretch.Uniform;

        this.Content = _arrowPath;

        this.PreviewMouseLeftButtonUp += SlideOutButton_MouseLeftButtonUp;
    }

    private void SlideOutButton_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        PointAnimation pointAnim = new PointAnimation();
        pointAnim.From = new Point(0, 0);
        pointAnim.To = new Point(2, 0);
        Point point = (_pathSegments.ElementAt(0) as LineSegment).Point;
        LineSegment segment = (_pathSegments.ElementAt(0) as LineSegment);
        segment.BeginAnimation(LineSegment.PointProperty, pointAnim);

        PointAnimation pointAnim2 = new PointAnimation();
        pointAnim2.From = new Point(2, 3);
        pointAnim2.To = new Point(0, 3);
        Point point2 = (_pathSegments.ElementAt(1) as LineSegment).Point;
        LineSegment segment2 = (_pathSegments.ElementAt(1) as LineSegment);
        segment2.BeginAnimation(LineSegment.PointProperty, pointAnim2);

        PointAnimation pointAnim3 = new PointAnimation();
        pointAnim3.From = new Point(0, 6);
        pointAnim3.To = new Point(2, 6);
        Point point3 = (_pathSegments.ElementAt(2) as LineSegment).Point;
        LineSegment segment3 = (_pathSegments.ElementAt(2) as LineSegment);
        segment3.BeginAnimation(LineSegment.PointProperty, pointAnim3);
    }

    private PathGeometry _CreatePathGeo(bool left = false)
    {
        PathGeometry pathGeo = new PathGeometry();
        PathFigure figure = new PathFigure();
        PathSegmentCollection pathSegments = new PathSegmentCollection();

        pathSegments.Clear();

        if (!left)
        {
            pathSegments.Add(new LineSegment(new Point(0, 0), true));
            pathSegments.Add(new LineSegment(new Point(2, 3), true));
            pathSegments.Add(new LineSegment(new Point(0, 6), true));
        }
        else
        {
            pathSegments.Add(new LineSegment(new Point(2, 0), true));
            pathSegments.Add(new LineSegment(new Point(0, 3), true));
            pathSegments.Add(new LineSegment(new Point(2, 6), true));
        }

        figure.Segments = pathSegments;
        pathGeo.Figures.Add(figure);
        return pathGeo;
    }
}

Also please let me know if you can think of a more simple way to create this animation. (Using C# only).

Thanks!


Solution

  • After doing some debugging I found out that the issue was that there is an extra point in my path.

    The PathFigure class has a property on it called StartPoint. When I created my path, I had 4 points total, including the StartPoint.

    To fix this, I have to use the PathFigures StartPoint as my first point:

    Point starPoint = (_arrowPath.Data as PathGeometry).Figures[0].StartPoint;
    

    Then I only add two line segments to be the next two points:

    _pathSegments.Add(new LineSegment(new Point(2, 3), true));
    _pathSegments.Add(new LineSegment(new Point(0, 6), true));
    

    I then use these three points to animate.