Animate a path like it's drawn on a canvas

前端 未结 3 462
情书的邮戳
情书的邮戳 2021-01-06 03:34

I\'m a newbie in WPF and please, guide me in the right direction for this problem.

I have built a WPF application which contains all the functionality of that of a r

相关标签:
3条回答
  • 2021-01-06 03:59

    I am not quite sure if this is what you are looking for, but I'll give it a shot.

    The animation would be a bit complex. It would actually be a series of animations, one for each point in your path minus the first point. You would want to add point to the animated path, one at a time, from the source path. Each time you add a point, that point starts at the previous point, and travels to the desired point. The animation would move the newly added point along over time, giving the effect of that segment being "drawn". When that animation completes, you iterate to your next point and begin the next animation.

    0 讨论(0)
  • 2021-01-06 04:04

    I don't won't it to be amidst of comments, here's a great post:

    http://social.msdn.microsoft.com/Forums/en/wpf/thread/19a7bd4b-cf28-4b31-a329-a5f58b9ec374

    and here's is Charles Petzold's take on the problem:

    http://www.charlespetzold.com/blog/2006/08/150351.html

    0 讨论(0)
  • 2021-01-06 04:08

    TL;DR: We take advantage of the PointAnimationUsingPath. We animate a point along the path and build a Clip geometry as the point is moving.


    Full answer:

    I start by drawing a sample Path in a Grid for demonstration purposes. Put the actual Path data in resources because we will re-use it later.

    <Grid>
        <Grid.Resources>
            <PathGeometry x:Key="path">
                <PathFigure>
                    <BezierSegment Point1="10 30" Point2="100 100" Point3="200 10" />
                </PathFigure>
            </PathGeometry>
        </Grid.Resources>
        <Path x:Name="myPath" StrokeThickness="5" Stroke="Black" Data="{StaticResource path}" />
    </Grid>
    

    Then I define an empty Clip geomtery for the Path:

    <Path.Clip>
        <GeometryGroup x:Name="geometryGroup" FillRule="Nonzero"/>
    </Path.Clip>
    

    So far, the Path disappeared because it is clipped to an empty geometry. What we have left to do is progressively add points back in this clipping geometry to reveal the Path. For that, we need an object to animate. I suggest to create a FrameworkPoint for the demonstration:

    public class FrameworkPoint : FrameworkElement {
        public static DependencyProperty CenterProperty = DependencyProperty.RegisterAttached("Center", typeof(Point), typeof(FrameworkPoint));
        public Point Center { get => (Point)GetValue(CenterProperty); set => SetValue(CenterProperty, value); }
    
        public event Action<Point> CoordinatesChanged;
    
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) {
            base.OnPropertyChanged(e);
            if (e.Property == CenterProperty) {
                CoordinatesChanged?.Invoke(Center);
            }
        }
    }
    

    This is an object with only one property of type Point, and this property is animatable. Let's add our (invisible) point in the Grid and animate it on our Path:

    <local:FrameworkPoint x:Name="myPoint">
        <local:FrameworkPoint.Triggers>
            <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <PointAnimationUsingPath Duration="00:00:10"
                                                 Storyboard.TargetProperty="Center"
                                                 PathGeometry="{StaticResource path}"/>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </local:FrameworkPoint.Triggers>
    </local:FrameworkPoint>
    
    

    At start-up, the FrameworkPoint will invisibly follow the Path over the indicated time (10 seconds). All is left to do is build our Clip as the point moves:

    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            myPoint.CoordinatesChanged += MyPoint_CoordinatesChanged;
        }
    
        private void MyPoint_CoordinatesChanged(Point obj) {
            geometryGroup.Children.Add(new EllipseGeometry(obj, 5, 5));
        }
    }
    

    This won't give perfect results for fast animations because the sampling won't be good enough but it could give you ideas!

    0 讨论(0)
提交回复
热议问题