C# WPF 动画在错误的地方跳跃和结束

Posted

技术标签:

【中文标题】C# WPF 动画在错误的地方跳跃和结束【英文标题】:C# WPF animation jumping and ending in wrong place 【发布时间】:2015-03-13 16:00:08 【问题描述】:

我的一些功能有问题... 下面是一个对象,并简单地将其沿 x 轴移动指定数量的像素。 (我在 y 轴上有另一个)

private void AnimObject_Horizontal( FrameworkElement p_Object, double p_X, int p_Millisec ) 
        // Find out the actual position on the screen
        Point l_Start = p_Object.TransformToAncestor( m_Canvas ).Transform( new Point( 0, 0 ) );

        // Adjust the position, subtracting the Margins, that are set at initialization, because the margin is automaticly added to the PathPoints by C# 
        l_Start.X -= p_Object.Margin.Left;
        l_Start.Y -= p_Object.Margin.Top;

        // Create the path for the object to follow. Moving horizontally is just a straight line, so I just need to set the StartPoint and add a single point, which will be the end
        PathGeometry l_PathGeo = new PathGeometry();
        PathFigure l_PathFigure = new PathFigure();
        l_PathFigure.StartPoint = new Point(l_Start.X, l_Start.Y);
        LineSegment l_LineSegment = new LineSegment( new Point(l_Start.X + p_X, l_Start.Y ), false);
        l_PathFigure.Segments.Add( l_LineSegment );
        l_PathGeo.Figures.Add( l_PathFigure );
        l_PathGeo.Freeze();

        // Create both DoubleAnimations that animate the X and Y value of the given Object
        Transform l_Transform_ = new TranslateTransform();
        DoubleAnimationUsingPath translateXAnimation_ = new DoubleAnimationUsingPath();
        translateXAnimation_.PathGeometry = l_PathGeo;
        translateXAnimation_.Duration = TimeSpan.FromMilliSeconds( p_Millisec  );
        translateXAnimation_.Source = PathAnimationSource.X;

        DoubleAnimationUsingPath translateYAnimation_ = new DoubleAnimationUsingPath();
        translateYAnimation_.PathGeometry = l_PathGeo;
        translateYAnimation_.Duration = TimeSpan.FromMilliSeconds( p_Millisec  );
        translateYAnimation_.Source = PathAnimationSource.Y;

        // Set the object as animationtarget and add Eventhandler (One is enough, because they will both end at the same time (Almost atleast)
        p_Object.RenderTransform = l_Transform_;
        Storyboard.SetTarget( translateXAnimation_, p_Object );
        translateXAnimation_.Completed += AnimationHorizontalComplete;

        // Start both animations
        l_Transform_.BeginAnimation( TranslateTransform.XProperty, translateXAnimation_ );
        l_Transform_.BeginAnimation( TranslateTransform.YProperty, translateYAnimation_ );
    

当这个物体移动四分之一圈时:

private void AnimObject_LeftToBottom( FrameworkElement p_Object, double p_Radius, int p_Millisec ) 
        Point l_Start = p_Object.TransformToAncestor( m_Canvas ).Transform( new Point( 0, 0 ) );
        l_Start.X -= p_Object.Margin.Left;
        l_Start.Y -= p_Object.Margin.Top;

        // Convert 15 degrees to radians
        double l_Angle_15 = 15 * Math.PI / 180;

        PathGeometry l_Path = new PathGeometry();
        PathFigure l_Figure = new PathFigure();
        l_Figure.StartPoint = l_Start;
        PolyBezierSegment l_BezierSegment = new PolyBezierSegment();

        // Create a quarter-circle-path with beziersegmens. There will be the Startpoint and another point each 15 degrees to form a quarter-circle.             
        for ( int i = 1 ; i < 7 ; i++ ) 
            l_BezierSegment.Points.Add( new Point( l_Start.X + p_Radius * Math.Sin( l_Angle_15 * i ), l_Start.Y + p_Radius - p_Radius * Math.Cos( l_Angle_15 * i ) ) );
        

        l_Figure.Segments.Add( l_BezierSegment );
        l_Path.Figures.Add( l_Figure );
        l_Path.Freeze();

        Transform l_Transform_ = new TranslateTransform();
        DoubleAnimationUsingPath translateXAnimation_ = new DoubleAnimationUsingPath();
        translateXAnimation_.PathGeometry = l_Path;
        translateXAnimation_.Duration = TimeSpan.FromMilliSeconds( p_Millisec  );
        translateXAnimation_.Source = PathAnimationSource.X;

        DoubleAnimationUsingPath translateYAnimation_ = new DoubleAnimationUsingPath();
        translateYAnimation_.PathGeometry = l_Path;
        translateYAnimation_.Duration = TimeSpan.FromMilliSeconds( p_Millisec  );
        translateYAnimation_.Source = PathAnimationSource.Y;

        p_Object.RenderTransform = l_Transform_;
        Storyboard.SetTarget( translateXAnimation_, p_Object );
        translateXAnimation_.Completed += AnimationLeftBotComplete;
        l_Transform_.BeginAnimation( TranslateTransform.XProperty, translateXAnimation_ );
        l_Transform_.BeginAnimation( TranslateTransform.YProperty, translateYAnimation_ );
    

如您所见,我在这些函数中添加了“已完成”事件并将它们链接起来。我在画布上添加了一个图像,当我按下按钮时,图像首先沿 x 轴移动,然后在底部做一个四分之一圆,然后沿 y 轴移动。

我的问题是: 图像从 100,100 开始,应该移动到 200,100,一旦到达这个位置,它应该向下移动一个圆圈。 然而,在达到 200,100 之前不久,它会跳转到第二个动画起点。 (或者它只是没有在它应该结束的地方结束) 看看图片,这可能有助于理解我用我有点蹩脚的英语想说的话;) AnimationProblem on tinypic

有人知道这种行为的原因吗?

提前问候和感谢, 雪拉

【问题讨论】:

完全偏离主题,但该代码急需绿色文本! 你是说 cmets 吗?我删除了它们,因为帖子会更长...... 评论对两个人很有价值。未来的你(你会忘记它是如何运作的)和任何其他人。长篇文章比那些难以阅读代码的短篇文章更可取:) 我有 cmets,但不是英文的。在这里用英文添加它们 【参考方案1】:

自己修好了。 对于有同样问题的人:

以下代码行有点令人困惑,因为它没有按预期工作(至少在我看来)。

Point l_Start = p_Object.TransformToAncestor( m_Canvas ).Transform( new Point( 0, 0 ) );

即使我在 (100, 100) 处创建对象,上面代码的结果也会是 (108.3, 100)。起初我认为原因可能是窗口的边框(即使我将 Canvas 的 0,0 设置为参考点),但这不是问题。如果我进入全屏模式,它仍然是一样的,所以这不是原因。 我不知道 8.3 是从哪里来的,也不知道这个问题是否只存在于我身上,或者它是否是每台计算机的不同值。

【讨论】:

以上是关于C# WPF 动画在错误的地方跳跃和结束的主要内容,如果未能解决你的问题,请参考以下文章

跳跃的 CADisplayLink 动画

WPF 从 vb.net 代码开始动画给出错误

Webkit CSS 动画跳跃问题

c# wpf 的动画设计问题

C# Unity 动画

使用 CefSharp WPF 在 C# 上执行 JavaScript 会导致错误