【问题标题】:WPF: Animating along path geometryWPF:沿路径几何动画
【发布时间】:2016-04-26 11:16:17
【问题描述】:

我现在正在处理以下问题一周。请耐心等待我解释。

我想要实现的是,对于我们中的一些人来说,这很简单,但是刚接触 WPF 会让事情变得困难。

上面的图像是通过将(已经有)svg 转换为xaml 然后将其导入到 Visual Studio 来呈现的。这就是 xaml 的样子。

    <Canvas x:Name="Main" Margin="158,-223,-148,233">
        <Canvas.RenderTransform>
            <MatrixTransform Matrix="1.25 0 0 -1.25 -197.1231 961.58875"/>
        </Canvas.RenderTransform>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139746" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
            <Path.Data>
                <PathGeometry Figures="m 66.611178 552.33853 c -4.36996 0.6305 -8.8334 0.97293 -13.3752 0.97293 -18.11465 0 -35.027 -5.21161 -49.34949 -14.18974 l 21.64732 -36.67733 c 8.2963 5.25686 18.12667 8.31294 28.67512 8.31294 2.7121 0 5.37755 -0.20365 7.98106 -0.59283 l 2.23539 -0.38916 c 4.72288 -0.91109 9.2226 -2.43913 13.41755 -4.49964 l 35.933612 77.65818 c -12.53504 5.94167 -26.095762 10.06571 -40.347392 12.0342 0 0 -2.27764 -21.55688 -4.54327 -42.98252 l -2.2747 0.35297 z" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="#FFD3BC5F" Canvas.Left="401" Canvas.Top="-173" >
            <Path.Data>
                <PathGeometry x:Name="path139750" Figures="m -21.311892 515.98804 c -11.7053 -15.57594 -18.6547 -34.92004 -18.6622 -55.85694 l 35.53987 0 5.06525 -0.024 c 0.63507 11.4535 4.86922 21.94 11.58023 30.3706 l 1.44647 1.7423 c 2.94008 3.3894 6.29329 6.4077 9.98888 8.9736 l -43.53754 73.76488 c -13.18956 -8.30539 -24.88746 -18.76176 -34.60186 -30.87743 0 0 17.3968 -13.23944 34.61076 -26.3386 l -1.42986 -1.75428 z" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139780" Fill="#FFD3BC5F" Canvas.Left="401.4" Canvas.Top="-167.6">
            <Path.Data>
                <PathGeometry Figures="m 214.75854 460.1016 94.92962 0 0 69.86866 -94.92962 0 0 -69.86866 z" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139784" Fill="#FFD3BC5F" Canvas.Left="401.4" Canvas.Top="-167.6">
            <Path.Data>
                <PathGeometry Figures="m 211.64803 529.825 -36.87191 0 -62.32503 -69.72236 100.95576 0 0 69.74499 -1.75882 -0.0226 z" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  Fill="#FFD3BC5F" Canvas.Top="-173" Canvas.Left="401">
            <Path.Data>
                <PathGeometry x:Name="path139798" Figures="m -41.482092 460.131 -43.5377 0 c 0.6744 30.93022 11.4414 59.36853 29.1278 82.17137 l 33.3799 -25.40184 c -11.9001 -15.82789 -18.9641 -35.4887 -18.97 -56.76953" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139802" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
            <Path.Data>
                <PathGeometry Figures="m 139.82292 494.54117 c -13.01467 -14.5593 -25.97803 -29.06131 -30.40076 -34.00892 0 0 -2.72123 28.49563 -29.566602 43.70507 l 17.54746 37.92328 c 19.158502 -10.35383 34.278952 -27.22704 42.419902 -47.61943" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139806" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
            <Path.Data>
                <PathGeometry Figures="m 98.037008 543.53024 17.776782 38.41802 c 23.1211 -11.42479 42.62202 -29.06882 56.29587 -50.76297 l 0.18403 -0.31676 c 0 0 -15.53072 -17.37553 -31.34655 -35.06934 -8.34762 20.43762 -23.62341 37.33197 -42.910132 47.73105" FillRule="nonzero"/>
            </Path.Data>
        </Path>
        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139810" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
            <Path.Data>
                <PathGeometry Figures="m 53.235488 554.82033 c -18.39362 0 -35.56859 -5.28853 -50.11595 -14.3994 l -21.08756 35.73002 c 21.04842 12.78086 45.75185 20.14348 72.17809 20.14348 5.74697 0 11.40815 -0.36201 16.97265 -1.03931 l -4.37747 -41.4213 c -4.43321 0.63805 -8.96144 0.98651 -13.56976 0.98651" FillRule="nonzero"/>
            </Path.Data>
        </Path>

 <Rectangle Name="object_to_move" Fill="LightBlue" Height="36" Stroke="Black" Width="41" Canvas.Left="330" Canvas.Top="229"/>

我想要的是沿路径动画/移动框(矩形),使其(框)看起来像旅行,并使用它(路径)作为继续前进的道路。

我尝试过使用DoubleAnimationUsingPath。但是我很困惑,我认为我没有正确使用东西。

我找到了以下代码片段并尝试对其进行操作并将其应用到我的示例中,但无法使其正常工作。

 //  path139798.Freeze(); // For performance benefits. 
        DoubleAnimationUsingPath daPath = new DoubleAnimationUsingPath();
        daPath.Duration = TimeSpan.FromSeconds(5);
        daPath.RepeatBehavior = RepeatBehavior.Forever;
        daPath.AccelerationRatio = 0.6;
        daPath.DecelerationRatio = 0.4;
        daPath.AutoReverse = true;
        daPath.PathGeometry = path139798;
        daPath.Source = PathAnimationSource.X;
        circle2.BeginAnimation(Canvas.LeftProperty, daPath);


        daPath = new DoubleAnimationUsingPath();
        daPath.Duration = TimeSpan.FromSeconds(5);
        daPath.RepeatBehavior = RepeatBehavior.Forever;
        daPath.AccelerationRatio = 0.6;
        daPath.DecelerationRatio = 0.4;
        daPath.AutoReverse = true;
        daPath.PathGeometry = path139798;
        daPath.Source = PathAnimationSource.Y;
        circle2.BeginAnimation(Canvas.TopProperty, daPath);
    }

有人可以帮忙吗?谢谢!

【问题讨论】:

  • 哦,这看起来很有趣。所以我看到的所有定义都是path139798。这是否意味着您只是想让它遵循具有该名称的左下角第一个形状的路径?看起来您的其他形状几乎像迷宫一样开始,所以我想我会问,因为根据您的解释,我无法想象您想要的结果。
  • @ChrisW。嘿,感谢您抽出时间询问。我试图让框遵循我上面描述的形状,只有在代码示例中只是一个形状(你是对的),但是,代码示例不起作用。我只是想通过仅使用 1 个路径名来检查我是否做对了我没有做的事情来找出出路。再说一遍,我只是想让盒子沿着形状移动。
  • 好吧,你需要一个一致的路径来定义你的运动路径,注意将你的图片加载到油漆或其他东西中,然后画一条矩形应该作为路径的粗线?
  • @ChrisW。如果我只是把它画在那里,我可以从油漆中导入它吗?
  • 哦,不,大声笑,我的意思只是一个快速的模型,向我们展示预期的路径,这样我就可以举出一个例子。

标签: c# wpf xaml animation


【解决方案1】:

所以你的例子中有很多奇怪的边距和东西。我并没有把它弄得太多。我刚刚添加了一条运动路径并注意到了情节提要,但你去吧。

快速提示:Blend(Visual Studio 附带)使这些效果变得非常快速和简单。对于这个例子,我只是制作了形状路径来匹配你的模拟图像。然后就像选择它然后right-click -&gt; Path -&gt; Make Motion Path 一样简单,它会提示您选择要跟随路径的对象。加载 Blend 的时间比它制作示例的时间要长。

希望这会有所帮助,干杯。

<Canvas x:Name="Main" Height="1025 " Width="1025">
            <Canvas.Resources>
                <Storyboard x:Key="Weeeee" RepeatBehavior="Forever">
                    <DoubleAnimationUsingPath Duration="0:0:3" Source="X" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="object_to_move">
                        <DoubleAnimationUsingPath.PathGeometry>
                            <PathGeometry Figures="M0.83299852,-4.019 L0.83299852,0.6089829 L0.61794496,0.94214186 C-7.6701996,14.489389 -12.443,30.392629 -12.443001,47.403001 C-12.443,96.887715 27.948303,137.003 77.773499,137.003 C113.58536,137.003 144.52365,116.27938 159.09367,86.248303 L159.90265,84.471135 L380.931,84.471135 L380.931,86.871121 L160.63918,86.871121 L160.4838,87.217053 C145.62575,118.25356 114.07582,139.671 77.556,139.671 C26.745804,139.671 -14.444,98.212666 -14.444,47.071218 C-14.444,29.491346 -9.5768454,13.055669 -1.124851,-0.94513857 z"/>
                        </DoubleAnimationUsingPath.PathGeometry>
                    </DoubleAnimationUsingPath>
                    <DoubleAnimationUsingPath Duration="0:0:3" Source="Y" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="object_to_move">
                        <DoubleAnimationUsingPath.PathGeometry>
                            <PathGeometry Figures="M0.83299852,-4.019 L0.83299852,0.6089829 L0.61794496,0.94214186 C-7.6701996,14.489389 -12.443,30.392629 -12.443001,47.403001 C-12.443,96.887715 27.948303,137.003 77.773499,137.003 C113.58536,137.003 144.52365,116.27938 159.09367,86.248303 L159.90265,84.471135 L380.931,84.471135 L380.931,86.871121 L160.63918,86.871121 L160.4838,87.217053 C145.62575,118.25356 114.07582,139.671 77.556,139.671 C26.745804,139.671 -14.444,98.212666 -14.444,47.071218 C-14.444,29.491346 -9.5768454,13.055669 -1.124851,-0.94513857 z"/>
                        </DoubleAnimationUsingPath.PathGeometry>
                    </DoubleAnimationUsingPath>
                </Storyboard>
            </Canvas.Resources>
            <Canvas.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <BeginStoryboard Storyboard="{StaticResource Weeeee}"/>
                </EventTrigger>
            </Canvas.Triggers>
            <Canvas.RenderTransform>
                <MatrixTransform Matrix="1.25 0 0 -1.25 -197.1231 961.58875"/>
            </Canvas.RenderTransform>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139746" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
                <Path.Data>
                    <PathGeometry Figures="m 66.611178 552.33853 c -4.36996 0.6305 -8.8334 0.97293 -13.3752 0.97293 -18.11465 0 -35.027 -5.21161 -49.34949 -14.18974 l 21.64732 -36.67733 c 8.2963 5.25686 18.12667 8.31294 28.67512 8.31294 2.7121 0 5.37755 -0.20365 7.98106 -0.59283 l 2.23539 -0.38916 c 4.72288 -0.91109 9.2226 -2.43913 13.41755 -4.49964 l 35.933612 77.65818 c -12.53504 5.94167 -26.095762 10.06571 -40.347392 12.0342 0 0 -2.27764 -21.55688 -4.54327 -42.98252 l -2.2747 0.35297 z" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Fill="#FFD3BC5F" Canvas.Left="401" Canvas.Top="-173" >
                <Path.Data>
                    <PathGeometry x:Name="path139750" Figures="m -21.311892 515.98804 c -11.7053 -15.57594 -18.6547 -34.92004 -18.6622 -55.85694 l 35.53987 0 5.06525 -0.024 c 0.63507 11.4535 4.86922 21.94 11.58023 30.3706 l 1.44647 1.7423 c 2.94008 3.3894 6.29329 6.4077 9.98888 8.9736 l -43.53754 73.76488 c -13.18956 -8.30539 -24.88746 -18.76176 -34.60186 -30.87743 0 0 17.3968 -13.23944 34.61076 -26.3386 l -1.42986 -1.75428 z" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139780" Fill="#FFD3BC5F" Canvas.Left="401.4" Canvas.Top="-167.6">
                <Path.Data>
                    <PathGeometry Figures="m 214.75854 460.1016 94.92962 0 0 69.86866 -94.92962 0 0 -69.86866 z" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139784" Fill="#FFD3BC5F" Canvas.Left="401.4" Canvas.Top="-167.6">
                <Path.Data>
                    <PathGeometry Figures="m 211.64803 529.825 -36.87191 0 -62.32503 -69.72236 100.95576 0 0 69.74499 -1.75882 -0.0226 z" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  Fill="#FFD3BC5F" Canvas.Top="-173" Canvas.Left="401">
                <Path.Data>
                    <PathGeometry x:Name="path139798" Figures="m -41.482092 460.131 -43.5377 0 c 0.6744 30.93022 11.4414 59.36853 29.1278 82.17137 l 33.3799 -25.40184 c -11.9001 -15.82789 -18.9641 -35.4887 -18.97 -56.76953" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139802" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
                <Path.Data>
                    <PathGeometry Figures="m 139.82292 494.54117 c -13.01467 -14.5593 -25.97803 -29.06131 -30.40076 -34.00892 0 0 -2.72123 28.49563 -29.566602 43.70507 l 17.54746 37.92328 c 19.158502 -10.35383 34.278952 -27.22704 42.419902 -47.61943" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139806" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
                <Path.Data>
                    <PathGeometry Figures="m 98.037008 543.53024 17.776782 38.41802 c 23.1211 -11.42479 42.62202 -29.06882 56.29587 -50.76297 l 0.18403 -0.31676 c 0 0 -15.53072 -17.37553 -31.34655 -35.06934 -8.34762 20.43762 -23.62341 37.33197 -42.910132 47.73105" FillRule="nonzero"/>
                </Path.Data>
            </Path>
            <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139810" Fill="#FFD3BC5F" Canvas.Left="399.4" Canvas.Top="-172.6">
                <Path.Data>
                    <PathGeometry Figures="m 53.235488 554.82033 c -18.39362 0 -35.56859 -5.28853 -50.11595 -14.3994 l -21.08756 35.73002 c 21.04842 12.78086 45.75185 20.14348 72.17809 20.14348 5.74697 0 11.40815 -0.36201 16.97265 -1.03931 l -4.37747 -41.4213 c -4.43321 0.63805 -8.96144 0.98651 -13.56976 0.98651" FillRule="nonzero"/>
                </Path.Data>
            </Path>

            <!-- Trajectory -->
            <Path Data="M16.276999,1 L16.276999,5.627983 16.061945,5.9611419 C7.7738004,19.508389 3.0009999,35.41163 3.000999,52.422002 3.0009999,101.90672 43.392303,142.022 93.217499,142.022 129.02936,142.022 159.96765,121.29839 174.53767,91.267304 L175.34665,89.490136 396.375,89.490136 396.375,91.890122 176.08318,91.890122 175.9278,92.236054 C161.06975,123.27256 129.51982,144.69 93,144.69 42.189804,144.69 1,103.23167 1,52.090218 1,34.510346 5.8671546,18.07467 14.319149,4.0738615 z" Fill="#7F000000" Height="145.69" Canvas.Left="360.056" Stretch="Fill" Stroke="Red" StrokeThickness="2" Canvas.Top="236.648" Width="397.375"/>

            <!-- Because I like to move it, move it ~~ -->
            <Rectangle x:Name="object_to_move" Fill="LightBlue" Height="36" Stroke="Black" Width="41" Canvas.Left="355" Canvas.Top="223.667" RenderTransformOrigin="0.5,0.5">
                <Rectangle.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Rectangle.RenderTransform>
            </Rectangle>

        </Canvas>

...还有一个质量很差的 GIF,以便将其可视化以供其他观众观看。

【讨论】:

  • 这太好了,克里斯。为了使路径与形状匹配,您是否将其导入混合而不是绘制它?我试图重现您所解释的内容,但我无法完成。我找不到make motion path 选项(Blend 5)。请你帮忙。谢谢
  • @user3641381 是的,我刚刚将您的 xaml 混合并合并了一个椭圆和一条线的一部分,以创建您看到的路径。然后正如我所说,只需右键单击 -> 路径 -> 制作运动路径。我还使用了 VS2015 附带的最新 Blend,请确保在执行此操作时选择了路径。
  • 很棒的帮助,克里斯。得到它的工作!最后一个问题。你是怎么把路弄得这么顺利的?有了一些精确的点,我无法让它那么顺利!再次感谢!
  • @user3641381 您需要熟悉创建路径。对于复杂的东西,我在 Illustrator 中制作,然后导出到 xaml。对于这个例子,虽然我刚开始用一个椭圆作为圆形部分,然后将它合并到一个矩形作为直线部分。在 Blend 中,这些选项位于 Right-Click->Combine 下,这有点像 Illustrator 中的 Pathfinder 工具,如果您可能更熟悉该参考资料的话。不过,要习惯知道如何使用它们确实需要一些经验/修修补补。
【解决方案2】:

这是一个工作演示,可能会对 DoubleAnimationUsingPath 有所启发

<Window.Resources>
    <PathGeometry x:Key="AnimationPath" Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100" />
</Window.Resources>

<Grid>
    <Canvas x:Name="Main" >

        <!-- The Rectangle itself ... -->

        <Path xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Name="path139746" Fill="#FFD3BC5F">
            <Path.Data>
                <PathGeometry Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100" />
            </Path.Data>
        </Path>


        <Rectangle   
  Width="30" Height="30" Fill="Blue">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <RotateTransform x:Name="AnimatedRotateTransform" />
                    <TranslateTransform x:Name="AnimatedTranslateTransform"  />
                </TransformGroup>
            </Rectangle.RenderTransform>

            <Rectangle.Triggers>
                <EventTrigger RoutedEvent="Path.Loaded">
                    <BeginStoryboard>
                        <Storyboard RepeatBehavior="Forever" AutoReverse="True" >

                            <!-- Generates angle values (in degrees) from
               the path. This animation is used to
               rotate the rectangle. -->
                            <DoubleAnimationUsingPath
            Storyboard.TargetName="AnimatedRotateTransform"
            Storyboard.TargetProperty="Angle"
            PathGeometry="{StaticResource AnimationPath}"
            Source="Angle"
            Duration="0:0:5"  />

                            <!-- Generates horizontal offset values from
               the path. This animation is used to 
               animate the rectangle horizontally. -->
                            <DoubleAnimationUsingPath
            Storyboard.TargetName="AnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            PathGeometry="{StaticResource AnimationPath}"
            Source="X" 
            Duration="0:0:5"  />

                            <!-- Generates vertical offset values from
               the path. This animation is used to move
               the rectangle vertically. -->
                            <DoubleAnimationUsingPath
            Storyboard.TargetName="AnimatedTranslateTransform"
            Storyboard.TargetProperty="Y"
            PathGeometry="{StaticResource AnimationPath}"
            Source="Y" 
            Duration="0:0:5"  />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Rectangle.Triggers>
        </Rectangle>

    </Canvas>
</Grid>

如您所见,矩形遵循单一路径....它将遵循 path139798 但它看起来不正确,因为这是一个多边形,如果您希望矩形遵循形状的中心线(PathGeometry Figures)您需要定义动画路径的中心线

【讨论】:

  • 我会尝试一下并回复您。感谢您抽出时间。我正在考虑为动画定义一条线。但是,除了手动计算点之外,还有更简单的方法来定义它吗?我的意思是Figures="M 10,100 C 35,0 135,0 160,100 180,190 285,200 310,100
猜你喜欢
  • 1970-01-01
  • 2013-04-29
  • 2012-10-29
  • 1970-01-01
  • 2023-03-25
  • 2011-09-28
  • 2015-07-15
  • 2018-05-23
  • 2014-02-05
相关资源
最近更新 更多