我可以单独为WPF Bezier曲线控制点的X坐标和Y坐标设置动画吗?

时间:2015-03-15 11:44:21

标签: c# wpf animation

我正在尝试在WPF中创建一个动画Bezier曲线,我打算制作一个#34;生活"通过平滑和缓慢的动画终点和控制点。我不希望任何一点遵循明显可预测的路径,如简单的椭圆或圆。

我通过使用两个不同的DoubleAnimations在其他更简单的动画上取得了成功,动画分别为Canvas.Top和Canvas.Left动画。

但是在Bezier段中,控制点和端点都是Point()实例,我似乎无法弄清楚如何设置这些Point实例的动画。 X和Y分别坐标。虽然有(例如)BezierSegment.ControlPoint2的PropertyPath,但似乎并不是该点的X坐标。

我已经看过通过继承PointAnimationBase来实现我自己的自定义点动画,但很难浏览文档来理解它们是如何结合在一起的 - 并且那里没有很多例子。 / p>

继承PointAnimationBase的自定义动画是正确的方法吗?如何将其绑定到BezierSegment的控制点?或者我应该看一些完全不同的东西来达到效果?

1 个答案:

答案 0 :(得分:1)

自定义PointAnimation似乎是一种明智的方法。

以下XAML显示了标准PointAnimation如何为QuadraticBezierSegment的Point1属性设置动画:

<Path Stroke="Black" StrokeThickness="3">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigure StartPoint="100,200">
                    <PathFigure.Segments>
                        <QuadraticBezierSegment Point2="200,200"/>
                    </PathFigure.Segments>
                </PathFigure>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
    <Path.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <PointAnimation
                        Storyboard.TargetProperty="Data.Figures[0].Segments[0].Point1"
                        From="150,200" To="150,0" Duration="0:0:1"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Path.Triggers>
</Path>

自定义PointAnimation需要您实现GetCurrentValueCore方法并返回表示动画当前值的Point实例,具体取决于animationClock参数提供的当前时间:

public class MyPointAnimation : PointAnimationBase
{
    protected override Point GetCurrentValueCore(
        Point defaultOriginValue, Point defaultDestinationValue,
        AnimationClock animationClock)
    {
        double x = ... // as function of animationClock
        double y = ... // as function of animationClock
        return new Point(x, y);
    }

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