WPF动画弯曲并遵循一些路径几何

时间:2013-06-13 18:02:09

标签: c# wpf animation

好的,所以我正在加载屏幕上工作,我想把它发光一点。

基本上我要做的是沿着路径几何数据动画一个对象 ...我强调'沿',因为在切线上沿着路径保持一个固定的对象不是我想要的做

这是我想要做的最佳代表:

enter image description here

我可以使用矩阵变换沿路径发送此边框元素,但它会随着切线动画的出现而移动并随路径一起旋转,但不会弯曲以适合路径的形状...这里就是一个例子:

<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>

我想出了一个看起来非常敏锐的替代解决方案,但我想向社区提出这个问题,看看他们是否有任何关于如何完成这项任务的想法(或者甚至可能)。我在这个问题上做了一些广泛的谷歌搜索,并没有提出如何以有效的方式实现这一目标。

要求:

  1. 必须遵循(或“弯曲”)路径
  2. 它必须能够在不破坏动画的情况下进行缩放(我见过的许多笔画动画表示只能在不重新配置动画属性的情况下以一种尺寸运行)...视图框完全可以接受完成这个
  3. 如果形状可以逐渐变细并在尾侧上消失,这将是一个更大的优势(见上图),但这可能超过可能

    编辑: 澄清我的意思是'弯曲'......我的意思是下面的图B ......图A是我传统上看到的标准:

    enter image description here

2 个答案:

答案 0 :(得分:4)

在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>

需要注意的一点是,剪切区域需要应用于Canvas个对象。如果它们应用于Path对象,就像您通常对图像所做的那样,那么剪裁区域随Path一起被RenderTrasform旋转。不是预期的效果。

答案 1 :(得分:1)

你可以在路径上放置很多圆圈并为它们的直径设置动画。