WPF路径动画

5
我已经创建了以下XAML。
<Canvas Background="Gray" Margin="10">    
    <Ellipse x:Name="Node1" Width="20" Height="20" Fill="AliceBlue" Canvas.Left="38" Canvas.Top="136" />
    <Ellipse x:Name="Node2" Width="20" Height="20" Fill="AliceBlue" Canvas.Left="290" Canvas.Top="136" />
    <Ellipse x:Name="object" Width="10" Height="20" Fill="Black" Canvas.Left="43" Canvas.Top="125" />
    <Path Stroke="Black" StrokeThickness="1">
        <Path.Data>
            <PathGeometry>
                <PathGeometry.Figures>
                    <PathFigureCollection>
                        <PathFigure StartPoint="50,145">
                            <PathFigure.Segments>
                                <PathSegmentCollection>
                                    <LineSegment Point="100,100" />
                                    <LineSegment Point="250,100" />
                                    <LineSegment Point="300,145" />
                                </PathSegmentCollection>
                            </PathFigure.Segments>
                        </PathFigure>
                    </PathFigureCollection>
                </PathGeometry.Figures>
            </PathGeometry>
        </Path.Data>
    </Path>
</Canvas>

如您所见,我创建了两个椭圆形节点。连接这两个节点的路径和一个坐落在节点1上的对象。我想做的就是将节点1上的对象沿着路径朝向节点2进行动画处理。
我试图使用代码实现动画效果,因为我希望在单击节点2时发生动画。我一直在尝试使用DoubleAnimation、MatrixAnimation、Storyboard等方法,但非常令人困惑。请分享您的知识,告诉我如何实现这个目标。我希望同样的代码也可以适用于曲线和复杂路径。
1个回答

2
你需要使用 DoubleAnimationUsingPath (参考)
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="WpfApplication1.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">
    <Window.Resources>
        <Storyboard x:Key="Storyboard1">
            <DoubleAnimationUsingPath Duration="0:0:2" Source="X" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="object">
                <DoubleAnimationUsingPath.PathGeometry>
                    <PathGeometry Figures="M2,10 L52,-35 L202,-35 L252,10"/>
                </DoubleAnimationUsingPath.PathGeometry>
            </DoubleAnimationUsingPath>
            <DoubleAnimationUsingPath Duration="0:0:2" Source="Y" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="object">
                <DoubleAnimationUsingPath.PathGeometry>
                    <PathGeometry Figures="M2,10 L52,-35 L202,-35 L252,10"/>
                </DoubleAnimationUsingPath.PathGeometry>
            </DoubleAnimationUsingPath>
        </Storyboard>
    </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <Canvas Background="Gray" Margin="10">    
    <Ellipse x:Name="Node1" Width="20" Height="20" Fill="AliceBlue" Canvas.Left="38" Canvas.Top="136" />
    <Ellipse x:Name="Node2" Width="20" Height="20" Fill="AliceBlue" Canvas.Left="290" Canvas.Top="136" />
    <Ellipse x:Name="object" Width="10" Height="20" Fill="Black" Canvas.Left="43" Canvas.Top="125" RenderTransformOrigin="0.5,0.5" MouseLeftButtonDown="object_MouseLeftButtonDown" >
        <Ellipse.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform/>
                <TranslateTransform/>
            </TransformGroup>
        </Ellipse.RenderTransform>
    </Ellipse>
    <Path Stroke="Black" StrokeThickness="1">
        <Path.Data>
            <PathGeometry>
                <PathGeometry.Figures>
                    <PathFigureCollection>
                        <PathFigure StartPoint="50,145">
                            <PathFigure.Segments>
                                <PathSegmentCollection>
                                    <LineSegment Point="100,100" />
                                    <LineSegment Point="250,100" />
                                    <LineSegment Point="300,145" />
                                </PathSegmentCollection>
                            </PathFigure.Segments>
                        </PathFigure>
                    </PathFigureCollection>
                </PathGeometry.Figures>
            </PathGeometry>
        </Path.Data>
    </Path>
</Canvas>
</Grid>
</Window>

然后从代码中调用:

private void object_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    Storyboard animation = this.TryFindResource("Storyboard1") as Storyboard;
    animation.Begin();
}

[编辑] 我认为你漏掉了一个关键工具:Blend。至于在代码中创建动画,如果你看看XAML元素,把它们看作序列化类,在代码中可以进行反射,即:

    Storyboard sb = new Storyboard();
    DoubleAnimationUsingPath ani_2 = new DoubleAnimationUsingPath();
    ani_2.Duration = new Duration(new TimeSpan(0, 0, 2));

    PathGeometry pg = new PathGeometry();
    pg.Figures.Add(new PathFigure());

    ani_2.PathGeometry.AddGeometry(pg);

等等。然而从代码中创建这些内容(依我所见)相当麻烦。这完全取决于应用程序。 请点击这里,以获取有关Blend的起点。


我使用了你的方法进行测试,它运行良好。但是,我仍然不明白这里有一些事情。你是如何创建在动画中使用的路径几何图形的?如果我需要通过C#代码创建它们,该怎么做呢?例如,假设我需要在用户绘制的路径上对此对象进行动画处理,我该如何将路径转换为路径几何图形? - SysAdmin
为什么动画结束后Canvas.GetLeft(@object)没有改变?如果您能提供一个好的教程链接来理解这些基础知识,那将非常有帮助。 - SysAdmin
不太确定,但从代码看来,Path.Data 包含 Path.Geometry,也许可以将其用作 DoubleAnimationUsingPath.PathGeometry?不过我会留给你自己去研究的 ;) - StaWho
尝试过了,但不起作用。Path.Data给出路径的绝对路径几何形状。它对应于我们在XAML中提供的内容。但是,我们提供给动画的pathgeometry会偏移一定量的X、Y,以便从0,0开始。在上面的例子中,如果我们从X中减去48,从Y中减去135,就可以得到动画pathgeometry。 - SysAdmin
从路径的坐标中减去起始点如何?您可能需要调整“对象”的枢轴(观察其在开始动画时的行为)。 - StaWho
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接