2015-06-02 48 views
1

我有一個WPF Storyboard(與RepeatBehavior=Forever)包含兩個DoubleAnimationUsingPath動畫。這些動畫跟蹤了一條圓形路徑,我通過添加一個EllipseGeometry創建。一個動畫用於控制X位置,另一個動畫用於控制另一個物體的Y位置,該物體使用圓形路徑出現在軌道上。玩DoubleAnimationUsingPath反向

動畫始終沿着順時針方向的路徑,始終在圓的右側中間開始。我需要強制動畫反向播放(即逆時針沿着路徑)。理想情況下,我也希望能夠控制起跑位置,但現在這不是必要的。

動畫的AutoReverse屬性做我想要的,但很明顯,然後它順時針和逆時針之間交替 - 我需要動畫循環,總是在逆時針方向。

我也嘗試使用ScaleTransformScaleX = -1爲了翻轉橢圓,希望這會有所幫助 - 但它沒有。

有沒有辦法強制DoubleAnimationUsingPath沿着路徑的特定方向?

回答

1

您可以使用相同的座標在兩條路徑之間切換,但是反向。這裏是一個使用MatrixAnimationUsingPath的示例,其中當UI元素加載時動畫方向爲cw,並且當鼠標指針進入藍色矩形時它將變爲ccw。

<Canvas ClipToBounds="False" Width="400" Height="400"> 
     <Path StrokeThickness="10" StrokeDashArray="" StrokeDashCap="Flat" StrokeDashOffset="0" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" StrokeLineJoin="Miter" StrokeMiterLimit="10" Stroke="#000000"> 
      <Path.Data> 
       <PathGeometry Figures="M 150,250 C 150,120 300,120 300,250 C 300,390 150,390 150,250 Z" /> 
      </Path.Data> 
     </Path> 
     <Rectangle Fill="Blue" RenderTransformOrigin="0.5,0.5" Width="10" Height="10" Margin="-5"> 
      <Rectangle.RenderTransform> 
       <TransformGroup> 
        <MatrixTransform x:Name="tt"> 
         <MatrixTransform.Matrix> 
          <Matrix /> 
         </MatrixTransform.Matrix> 
        </MatrixTransform> 
       </TransformGroup> 
      </Rectangle.RenderTransform> 
      <Rectangle.Triggers> 
       <EventTrigger RoutedEvent="FrameworkElement.Loaded"> 
        <BeginStoryboard> 
         <Storyboard> 
          <MatrixAnimationUsingPath Duration="0:0:05" Storyboard.TargetName="tt" 
                 Storyboard.TargetProperty="Matrix" 
                 AutoReverse="False" 
                 DoesRotateWithTangent="True" 
                 RepeatBehavior="Forever" 
                > 
           <MatrixAnimationUsingPath.PathGeometry> 
            <PathGeometry Figures="M 150,250 C 150,120 300,120 300,250 C 300,390 150,390 150,250 Z"> 
            </PathGeometry> 
           </MatrixAnimationUsingPath.PathGeometry> 
          </MatrixAnimationUsingPath> 
         </Storyboard> 
        </BeginStoryboard> 
       </EventTrigger> 
       <EventTrigger RoutedEvent="FrameworkElement.MouseEnter"> 
        <BeginStoryboard> 
         <Storyboard> 
          <MatrixAnimationUsingPath Duration="0:0:05" Storyboard.TargetName="tt" 
                 Storyboard.TargetProperty="Matrix" 
                 AutoReverse="False" 
                 DoesRotateWithTangent="True" 
                 RepeatBehavior="Forever" 
                > 
           <MatrixAnimationUsingPath.PathGeometry> 
            <PathGeometry Figures="M 150,250 C 150,390 300,390 300,250 C 300,120 150,120 150,250 Z" > 
            </PathGeometry> 
           </MatrixAnimationUsingPath.PathGeometry> 
          </MatrixAnimationUsingPath> 
         </Storyboard> 
        </BeginStoryboard> 
       </EventTrigger> 
      </Rectangle.Triggers> 
     </Rectangle> 
    </Canvas> 
+0

感謝您的建議。看起來關鍵是有兩條獨立的路徑 - 一條用於順時針方向,另一條用於逆時針方向。我希望找到一個解決方案,允許動畫使用單一路徑 - 或者,至少以編程方式操縱路徑以動態創建順時針和逆時針替代方案。 – John

1

DoubleAnimationUsingPath的替代方案可以是提供正弦值的自定義動畫。它有一個控制振幅的Amplitude屬性,並且它的符號也是竇動畫的方向。還有一個StartAngle屬性控制着動畫開始的角度。

public class SinusAnimation : DoubleAnimationBase 
{ 
    public static readonly DependencyProperty AmplitudeProperty = 
     DependencyProperty.Register(
      "Amplitude", typeof(double), typeof(SinusAnimation)); 

    public static readonly DependencyProperty StartAngleProperty = 
     DependencyProperty.Register(
      "StartAngle", typeof(double), typeof(SinusAnimation)); 

    public double Amplitude 
    { 
     get { return (double)GetValue(AmplitudeProperty); } 
     set { SetValue(AmplitudeProperty, value); } 
    } 

    public double StartAngle 
    { 
     get { return (double)GetValue(StartAngleProperty); } 
     set { SetValue(StartAngleProperty, value); } 
    } 

    protected override double GetCurrentValueCore(double defaultOriginValue, 
     double defaultDestinationValue, AnimationClock animationClock) 
    { 
     var result = defaultOriginValue; 
     var p = animationClock.CurrentProgress; 

     if (p.HasValue) 
     { 
      result = Amplitude * Math.Sin(
       p.Value * Math.PI * 2d + StartAngle * Math.PI/180d); 
     } 

     return result; 
    } 

    protected override Freezable CreateInstanceCore() 
    { 
     return new SinusAnimation(); 
    } 
} 

這是一些簡單的XAML,可以創建一個小的藍色圓圈的圓周運動。通過不同的振幅,它可能會創建橢圓軌跡,並通過不同的StartAngles以及各種利薩如圖。

<Canvas Margin="200"> 
    <Path Fill="Blue"> 
     <Path.Data> 
      <EllipseGeometry RadiusX="10" RadiusY="10"/> 
     </Path.Data> 
     <Path.Triggers> 
      <EventTrigger RoutedEvent="Loaded"> 
       <BeginStoryboard> 
        <Storyboard Duration="0:0:2" RepeatBehavior="Forever"> 
         <local:SinusAnimation 
          Storyboard.TargetProperty="(Canvas.Left)" 
          Amplitude="100" 
          Duration="0:0:2" RepeatBehavior="Forever"/> 
         <local:SinusAnimation 
          Storyboard.TargetProperty="(Canvas.Top)" 
          Amplitude="100" StartAngle="90" 
          Duration="0:0:2" RepeatBehavior="Forever"/> 
        </Storyboard> 
       </BeginStoryboard> 
      </EventTrigger> 
     </Path.Triggers> 
    </Path> 
</Canvas> 

編輯:爲了扭轉DoubleAnmationUsingPath你可以簡單地使用過的PathGeometry的Transform屬性設置爲一個適當的ScaleTransform:

<PathGeometry x:Key="path"> 
    <PathGeometry.Transform> 
     <ScaleTransform ScaleX="-1"/> 
    </PathGeometry.Transform> 
    ... 
</PathGeometry> 
+1

不錯!當我將'StartAngle'改爲「270」時,旋轉得到了扭轉。 –

+2

另外當您設置一個振幅爲負值。 – Clemens

+0

謝謝!這對於一個圓圈來說工作得非常好,儘管我希望找到一個可以使用任意路徑的解決方案。 – John