为什么我不能使用DoubleAnimationUsingPath为TranslateForm.X属性设置动画?

问题描述 投票:-1回答:1

我在wpf中创建了一个自定义Panel,在渲染后需要对子项进行动画处理。我想要给每个孩子的动画是使用贝塞尔曲线进行平移(移动)。

我跟随Microsoft's example并创建了AddAnimation方法,在其中我要添加Path的位置要使面板上的每个项目都动画化。

不幸的是,我得到了下面的异常:

无法在动画上为'X'属性设置动画'System.Windows.Media.TranslateTransform'使用'System.Windows.Media.Animation.DoubleAnimationUsingPath'

但是我应该如何在没有DoubleAnimationUsingPath的情况下为X属性设置动画?

这里是方法:

private void AddAnimation(FrameworkElement child, Point childLocation)
        {
            var middlePoint = GetMiddlePoint();
            var finalPoint = GetFinalPoint();

            var animatedTranslateTransform = new TranslateTransform();
            child.RenderTransform = animatedTranslateTransform;
            child.RenderTransformOrigin = new Point(0.5, 0.5);

            // Create the animation path.
            PathGeometry animationPath = new PathGeometry();
            PathFigure pFigure = new PathFigure();
            pFigure.StartPoint = childLocation;
            PolyBezierSegment pBezierSegment = new PolyBezierSegment();
            pBezierSegment.Points.Add(middlePoint);
            pBezierSegment.Points.Add(finalPoint);
            pFigure.Segments.Add(pBezierSegment);
            animationPath.Figures.Add(pFigure);

            // Freeze the PathGeometry for performance benefits.
            animationPath.Freeze();

            // Create a DoubleAnimationUsingPath to move the
            // rectangle horizontally along the path by animating 
            // its TranslateTransform.
            DoubleAnimationUsingPath translateXAnimation =
                new DoubleAnimationUsingPath();
            translateXAnimation.PathGeometry = animationPath;
            translateXAnimation.Duration = TimeSpan.FromSeconds(5);

            // Set the Source property to X. This makes
            // the animation generate horizontal offset values from
            // the path information. 
            translateXAnimation.Source = PathAnimationSource.X;

            // Set the animation to target the X property
            Storyboard.SetTarget(translateXAnimation, child);
            Storyboard.SetTargetProperty(translateXAnimation,
                new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.X)"));

            // Create a DoubleAnimationUsingPath to move the
            // rectangle vertically along the path by animating 
            // its TranslateTransform.
            DoubleAnimationUsingPath translateYAnimation =
                new DoubleAnimationUsingPath();
            translateYAnimation.PathGeometry = animationPath;
            translateYAnimation.Duration = TimeSpan.FromSeconds(5);

            // Set the Source property to Y. This makes
            // the animation generate vertical offset values from
            // the path information. 
            translateYAnimation.Source = PathAnimationSource.Y;

            // Set the animation to target the Y property
            // of the TranslateTransform named "AnimatedTranslateTransform".
            Storyboard.SetTarget(translateYAnimation, child);
            Storyboard.SetTargetProperty(translateYAnimation,
                new PropertyPath("(FrameworkElement.RenderTransform).(TranslateTransform.Y)"));

            // Create a Storyboard to contain and apply the animations.
            Storyboard pathAnimationStoryboard = new Storyboard();
            pathAnimationStoryboard.RepeatBehavior = RepeatBehavior.Forever;
            pathAnimationStoryboard.Children.Add(translateXAnimation);
            pathAnimationStoryboard.Children.Add(translateYAnimation);

            // Start the animations when the rectangle is loaded.
            child.Loaded += (sender, args) =>
            {
                Debug.WriteLine($"Child {child} loaded.");
                pathAnimationStoryboard.Begin(child);
            };
        }
c# wpf animation bezier
1个回答
1
投票

看一下AnimationException的InnerException属性。

产生异常的原因是,对于PolyBezierSegment,只有两个点是不够的,因为它需要两个控制点和一个端点,因此每条曲线需要三个点。

改为使用PolyQuadraticBezierSegment

var pBezierSegment = new PolyQuadraticBezierSegment();
pBezierSegment.Points.Add(middlePoint);
pBezierSegment.Points.Add(finalPoint);

或者只是QuadraticBezierSegment

var bezierSegment = new QuadraticBezierSegment();
bezierSegment.Point1 = middlePoint;
bezierSegment.Point2 = finalPoint;

该代码对于应该执行的操作似乎也太复杂了。您可以用两个DoubleAnimationUsingPath子项替换情节提要,并用单个MatrixAnimationUsingPath来动画MatrixMatrixTransform属性:

var animation = new MatrixAnimationUsingPath
{
    PathGeometry = animationPath,
    Duration = TimeSpan.FromSeconds(5)
};

var transform = new MatrixTransform();

child.RenderTransform = transform;
child.Loaded += (s, e) =>
    transform.BeginAnimation(MatrixTransform.MatrixProperty, animation);
© www.soinside.com 2019 - 2024. All rights reserved.