C# 弯曲并跟随某些路径几何体的WPF动画

C# 弯曲并跟随某些路径几何体的WPF动画,c#,wpf,animation,C#,Wpf,Animation,好的,我正在处理一个加载屏幕,我想把它放大一点 基本上,我想做的是沿路径几何体数据设置对象动画…我强调“沿”,因为我不想沿切线上的路径保持固定对象 这是我试图做的最好的表现: 我可以使用矩阵变换沿路径发送此边界元素,但它最终显示为切线动画,随路径移动和旋转,但不会弯曲以适应路径的形状…以下是一个示例: <Border Background="Black" BorderBrush="Transparent" Width="20" Height="20"> <Border.Ren

好的,我正在处理一个加载屏幕,我想把它放大一点

基本上,我想做的是沿路径几何体数据设置对象动画…我强调“沿”,因为我不想沿切线上的路径保持固定对象

这是我试图做的最好的表现:

我可以使用矩阵变换沿路径发送此边界元素,但它最终显示为切线动画,随路径移动和旋转,但不会弯曲以适应路径的形状…以下是一个示例:

<Border Background="Black" BorderBrush="Transparent" Width="20" Height="20">
<Border.RenderTransform>
    <MatrixTransform x:Name="MatrixT">
        <MatrixTransform.Matrix>
            <Matrix/>
        </MatrixTransform.Matrix>
    </MatrixTransform>
</Border.RenderTransform>
<Border.Triggers>
    <EventTrigger RoutedEvent="Border.Loaded">
        <BeginStoryboard>
            <Storyboard>
                <MatrixAnimationUsingPath Storyboard.TargetName="MatrixT" Storyboard.TargetProperty="Matrix" DoesRotateWithTangent="True" Duration="0:0:5" RepeatBehavior="Forever">
                    <MatrixAnimationUsingPath.PathGeometry>
                        <PathGeometry Figures="M201.1,50.501C201.1,78.138,178.737,100.501,151.1,100.501L150.799,100.501C123.162,100.501,114.933,77.834,100.8,50.501L100.8,50.5C86.666,23.167,78.437,0.5,50.8,0.5L50.5,0.5C22.863,0.5,0.500000000000014,22.863,0.500000000000014,50.5L0.500000000000014,50.501C0.500000000000014,78.138,22.863,100.501,50.5,100.501L50.8,100.501C78.437,100.501,86.666,77.834,100.8,50.501L100.8,50.5C114.933,23.167,123.162,0.5,150.799,0.5L151.1,0.5C178.736,0.5,201.1,22.863,201.1,50.501L201.1,50.501z" PresentationOptions:Freeze="True"/>
                    </MatrixAnimationUsingPath.PathGeometry>
                </MatrixAnimationUsingPath>
            </Storyboard>
        </BeginStoryboard>
    </EventTrigger>
</Border.Triggers>

我提出了一个看起来非常尖锐的替代解决方案,但我想向社区提出这个问题,看看他们对如何完成这项任务是否有任何想法(或者是否可能)…我在谷歌上做了大量的搜索,但没有找到有效的方法来实现这一点

要求:

  • 它必须沿着路径(或“弯曲”)
  • 它必须能够在不破坏动画的情况下缩放大小(我所看到的许多笔划动画表示只能在一个大小下运行,而无需重新配置动画属性)…viewbox完全可以实现这一点
  • 如果形状可以逐渐变细,并在尾端淡出,这将是一个更大的加号(见上图),但这可能超出了可能的范围

    编辑: 为了澄清我所说的“弯曲”是什么意思……我指的是下面的图B……图A是我传统上看到的标准:


    您可以在路径上放置许多圆并设置其直径的动画。

    在WPF中,将形状变形为路径将非常困难。但是,通过设置两条单独路径的动画,以及同时设置两个剪裁区域的动画,可以实现近似效果

    下面给出的是您想要的近似值的XAML。如果仔细观察无限符号的交叉点,您将注意到过渡期间着色的平滑度有轻微的不连续性。这是因为我对
    LinearGradientBrush
    对象的起点、终点和偏移点的设置有点随意。在这些方面做一点工作将使过渡顺利进行。您甚至可以选择为笔刷上的属性设置动画来帮助实现这一点

    <Window x:Class="AnimationTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525"
            Background="#FF486CBF">
      <Viewbox>
        <Grid>
          <Canvas Width="50" Height="50"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top">
            <Canvas.Clip>
              <RectangleGeometry Rect="0,0,50,55">
                <RectangleGeometry.Transform>
                  <TranslateTransform x:Name="_clip1"/>
                </RectangleGeometry.Transform>
              </RectangleGeometry>
            </Canvas.Clip>
            <Path StrokeStartLineCap="Round"
                  StrokeEndLineCap="Round"
                  StrokeThickness="10"
                  RenderTransformOrigin="0.5,0.8571"
                  Data="M 5,25 c 0,-25 40,-25 40,0">
              <Path.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                  <GradientStop Color="#FFFFFFFF" Offset="0"/>
                  <GradientStop Color="#00FFFFFF" Offset="0.7"/>
                </LinearGradientBrush>
              </Path.Stroke>
              <Path.RenderTransform>
                <RotateTransform x:Name="_rot1" />
              </Path.RenderTransform>
              <Path.Triggers>
                <EventTrigger RoutedEvent="Path.Loaded">
                  <BeginStoryboard>
                    <Storyboard>
                      <DoubleAnimation From="360" To="0"
                                       Duration="0:0:3"
                                       RepeatBehavior="Forever"
                                       Storyboard.TargetName="_rot1"
                                       Storyboard.TargetProperty="Angle"/>
                      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_clip1"
                             Storyboard.TargetProperty="Y"
                             RepeatBehavior="Forever">
                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:1.5" Value="25"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:2.8" Value="55"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:4.5" Value="-30"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:5.8" Value="0"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:6" Value="0"/>
                      </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                  </BeginStoryboard>
                </EventTrigger>
              </Path.Triggers>
            </Path>
          </Canvas>
    
          <Canvas Width="50" Height="50"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  Margin="40,0,0,0">
            <Canvas.Clip>
              <RectangleGeometry Rect="0,0,50,55">
                <RectangleGeometry.Transform>
                  <TranslateTransform x:Name="_clip2"/>
                </RectangleGeometry.Transform>
              </RectangleGeometry>
            </Canvas.Clip>
            <Path StrokeStartLineCap="Round"
                  StrokeEndLineCap="Round"
                  StrokeThickness="10"
                  RenderTransformOrigin="0.5,0.8571"
                  Data="M 5,25 c 0,-25 40,-25 40,0">
              <Path.Stroke>
                <LinearGradientBrush StartPoint="1,0" EndPoint="0,0">
                  <GradientStop Color="#FFFFFFFF" Offset="0"/>
                  <GradientStop Color="#00FFFFFF" Offset="0.7"/>
                </LinearGradientBrush>
              </Path.Stroke>
              <Path.RenderTransform>
                <RotateTransform x:Name="_rot2" />
              </Path.RenderTransform>
              <Path.Triggers>
                <EventTrigger RoutedEvent="Path.Loaded">
                  <BeginStoryboard>
                    <Storyboard>
                      <DoubleAnimation From="0" To="360"
                             Duration="0:0:3"
                             RepeatBehavior="Forever"
                             Storyboard.TargetName="_rot2"
                             Storyboard.TargetProperty="Angle"/>
                      <DoubleAnimationUsingKeyFrames Storyboard.TargetName="_clip2"
                             Storyboard.TargetProperty="Y"
                             RepeatBehavior="Forever">
                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="55"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:1.5" Value="-30"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:2.8" Value="0"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:4.5" Value="25"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:5.8" Value="55"/>
                        <DiscreteDoubleKeyFrame KeyTime="0:0:6" Value="55"/>
                      </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                  </BeginStoryboard>
                </EventTrigger>
              </Path.Triggers>
            </Path>
          </Canvas>
        </Grid>
      </Viewbox>
    </Window>
    
    
    

    需要注意的一点是,需要将剪裁区域应用于
    画布
    对象。如果它们应用于
    路径
    对象,就像通常对图像所做的那样,则剪裁区域将通过
    渲染器窗体
    路径
    旋转。不是期望的效果。

    您是否尝试过PathListbox hmmm…这是一个有趣的控件,我还没有见过,实际上我还有一些其他用途…但它最终仍然不允许对象沿路径弯曲/弯曲,沿着它切向旋转这实际上是在做你想做的事情,只需做一点谷歌搜索。我似乎仍然找不到任何与我想用它搜索的内容相关的东西…请看我刚才添加到问题中的第二张图片…PathListBox似乎允许你沿一条路径放置一组显示元素,但它不会扭曲元素的外观,使其沿路径弯曲(在旋转/平移/缩放之外),技术上,这是一个答案,但这并不理想…必须有更好的方法来完成此任务…另外,除非你把它放在超小的范围内,否则你必须要有很多圆圈才能看到它不是一条平滑的线。这取决于你认为什么是理想的和动画有多大。我目前的解决方案是使用一组7或8个圆,它们沿着路径并相互跟踪(彼此之间有空格),有点像你的解决方案……不过我要寻找的是一种使用路径几何体变形对象的方法,这不仅仅对动画很有用…我有一个很好的感觉,这是不可能的开箱即用,但是,如果我没有得到任何解决方案,这在未来几天左右,我会把这作为一个正确的问题的答案。“开箱即用”不可用。遵循一条路径是可能的:变形是一个不同的野兽:当一个片段位于非常锋利的边缘时会发生什么?是的,变形肯定会有挑战,但拥有这种能力仍然是有用的…锋利的边缘是一个问题,但这更像是一个不正确使用功能的问题,而不是一个问题