【问题标题】:Move object along path by property按属性沿路径移动对象
【发布时间】:2017-07-27 15:48:13
【问题描述】:

下面的代码在 DoubleAnimation 的帮助下沿路径移动对象

<Window x:Class="TestsForTrafficSimulator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestsForTrafficSimulator"
        mc:Ignorable="d"
        Title="MainWindow" Height="700" Width="1050">
    <Canvas x:Name="Main" Height="350 " Width="525">
        <Canvas.Resources>
            <Storyboard x:Key="Weeeee" RepeatBehavior="Forever">
                <DoubleAnimationUsingPath Duration="0:0:3" Source="X" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(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)[0].(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>
        <!-- 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"/>

        <Ellipse x:Name="object_to_move" Fill="LightBlue" Height="30" Stroke="Black" Width="30" Canvas.Left="355" Canvas.Top="223.667" RenderTransformOrigin="0.5,0.5">
            <Ellipse.RenderTransform>
                <TransformGroup>
                    <TranslateTransform/>
                </TransformGroup>
            </Ellipse.RenderTransform>
        </Ellipse>

    </Canvas>
</Window>

但是,我正在寻找一个选项,通过属性沿此路径移动对象。例如,带有Minimum=0 和Maximum=100 的滑块调节对象的“行进距离”。这意味着当 Slider 为 0 时,对象位于路径的开头,而在 100 时,对象位于路径的末尾。从头到尾的一半是 50。

我确信这个问题有一个相对简单的解决方案,但我似乎在互联网上搜索错误的关键字。

编辑:

经过进一步搜索,我很幸运,我找到了PathGeometry.GetPointAtFractionLength Method (Double, Point, Point),它可以用来获取路径上某个点的 X 和 Y 坐标。我用这个点来翻译对象。

目前正在运行,但如果有更好的解决方案,我仍然感兴趣

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    A 对代码进行了一些修改,我只是这样做,以便滑块将椭圆跟踪到滑块的值。我没有包括连续动画。我将把它留给你来整合所有需要的逻辑。

    XAML:

    <Canvas x:Name="Main" Height="350 " Width="525" Loaded="Main_OnLoaded">
    <Canvas.Resources>
        <Storyboard x:Key="Weeeee" RepeatBehavior="Forever" TargetName="object_to_move" Duration="0:0:3">
            <DoubleAnimationUsingPath  Duration="0:0:3" Source="X" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)" >
                <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)[0].(TranslateTransform.Y)" >
                <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>
    <!-- Trajectory -->
    <Slider x:Name="TestSlider" Width="200" Interval="1" Minimum="0" Maximum="1" ValueChanged="TestSlider_OnValueChanged"></Slider>
    <TextBox Canvas.Top="40" Width="100" Text="{Binding Value, ElementName=TestSlider}"></TextBox>
    <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"/>
    
    <Ellipse x:Name="object_to_move" Fill="LightBlue" Height="30" Stroke="Black" Width="30" Canvas.Left="355" Canvas.Top="223.667" RenderTransformOrigin="0.5,0.5">
        <Ellipse.RenderTransform>
            <TransformGroup>
                <TranslateTransform/>
            </TransformGroup>
        </Ellipse.RenderTransform>
    </Ellipse>
    

    变化:

    • 必须将持续时间添加到情节提要。
    • 添加的滑块将值范围为 0-1 以表示百分比。
    • 从 XAML 中删除了开始动画并将事件处理程序添加到 Canvas。

    代码背后:

        private void TestSlider_OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            Storyboard sb = Main.FindResource("Weeeee") as Storyboard;
            var ratio = sb.Duration.TimeSpan.TotalMilliseconds/2 * TestSlider.Value;
            sb.Seek(object_to_move, new TimeSpan(0,0,0,0,(int)ratio), TimeSeekOrigin.BeginTime);
            sb.Pause(object_to_move);            
        }
    
        private void Main_OnLoaded(object sender, RoutedEventArgs e)
        {
            Storyboard sb = Main.FindResource("Weeeee") as Storyboard;
            sb.Begin(object_to_move, true);
            sb.Stop(object_to_move);
        }
    

    注意事项:

    • Begin 方法需要从代码中调用,因为您需要设置 true 标志。这将设置isControllable 标志。我停止它只是为了不运行连续动画。
    • 我计算滑块与总持续时间的比率以确定位置。编辑这个,但你需要它。
    • .Seek 方法是魔术发生的地方,它将动画设置为给定的TimeSpan。
    • 我Pause,因为动画将在Seek 调用之后开始。

    这可以做得更漂亮,但它应该为您提供完成所需信息所需的信息。

    【讨论】:

    • 这是一个有效的解决方案!感谢您的贡献。但是,它与我的方法非常相似,感觉有点像 hack,因为我根本不想使用动画 - 这只是第一种方法。
    猜你喜欢
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    • 2020-04-05
    相关资源
    最近更新 更多