反向播放DoubleAnimationUsingPath

时间:2015-06-02 05:53:02

标签: wpf animation pathgeometry

我有一个包含两个Storyboard动画的WPF RepeatBehavior=ForeverDoubleAnimationUsingPath}。这些动画跟踪一个圆形路径,我通过添加EllipseGeometry创建。一个动画用于控制X位置,另一个动画用于控制另一个使用圆形路径进行轨道运动的物体的Y位置。

动画始终沿顺时针方向跟随路径,并始终从圆圈右侧的中间开始。我需要强制动画反向播放(即沿路径逆时针)。理想情况下,我也希望能够控制起始位置,但现在这不是必需的。

动画上的AutoReverse属性做了我想要的,但显然它在顺时针和逆时针之间交替 - 我需要动画循环,总是在逆时针方向。

我还尝试使用ScaleTransformScaleX = -1来翻转椭圆,希望这会有所帮助 - 但事实并非如此。

有没有办法迫使DoubleAnimationUsingPath遵循路径上的特定方向?

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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也可以创建各种Lissajous数字。

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