【问题标题】:Animate RenderTransform in WPFWPF 中的动画渲染转换
【发布时间】:2014-10-15 18:31:58
【问题描述】:

我有一个关于 C# 代码中 WPF 动画的问题!
我有一个 MouseWheel 事件的处理函数。它只是检查您是“放大”还是“缩小”。看一下代码,这里重要的一行是第 4 行,这里设置了 RenderTransform。

    private void ZoomPanCanvas_MouseWheel(object sender, MouseWheelEventArgs e) {
        var factor = (e.Delta > 0) ? (1.1) : (1 / 1.1);
        currrentScale = factor * currrentScale;
        mNetworkUI.RenderTransform = new ScaleTransform(currrentScale, currrentScale);
        var pos = e.GetPosition(mNetworkUI);
        mNetworkUI.Width = ZoomPanCanvas.ActualWidth / currrentScale;
        mNetworkUI.Height = ZoomPanCanvas.ActualHeight /currrentScale;
        var dummyTransform = new ScaleTransform(factor, factor, pos.X, pos.Y);
        var offSet = new Point(dummyTransform.Value.OffsetX, dummyTransform.Value.OffsetY);
        mNetworkUI.ViewModel.Network.SetTransformOffset(offSet);
    }

为了完整起见,我将函数的其余部分保留在代码中。
我想要做的是对 RenderTransform 的这种变化进行动画处理

我已经尝试使用 Storyboard(设置了 UIElement.RenderTransformProperty)。最好的结果是对 RenderTransform 进行非动画更改(但它与代码中的第 4 行实现的结果不同)。

也许你可以帮助我,我已经尝试了这里其他问题的一些建议方法。

编辑:

这是无效的尝试,首先是上面的 chenged 代码:

    private void ZoomPanCanvas_MouseWheel(object sender, MouseWheelEventArgs e) {
        var factor = (e.Delta > 0) ? (1.1) : (1 / 1.1);
        currrentScale = factor * currrentScale;
        ///mNetworkUI.RenderTransform = new ScaleTransform(currrentScale, currrentScale);
        Helper.Animations.RenderTransformAnimation(mNetworkUI, new ScaleTransform(currrentScale, currrentScale));
        var pos = e.GetPosition(mNetworkUI);
        mNetworkUI.Width = ZoomPanCanvas.ActualWidth / currrentScale;
        mNetworkUI.Height = ZoomPanCanvas.ActualHeight /currrentScale;
        var dummyTransform = new ScaleTransform(factor, factor, pos.X, pos.Y);
        var offSet = new Point(dummyTransform.Value.OffsetX, dummyTransform.Value.OffsetY);
        mNetworkUI.ViewModel.Network.SetTransformOffset(offSet);
    }

它遵循静态辅助函数:

    public static void RenderTransformAnimation(FrameworkElement element, Transform newTransform) {
        MatrixAnimationUsingKeyFrames anim = new MatrixAnimationUsingKeyFrames();
        var key1 = new DiscreteMatrixKeyFrame(element.RenderTransform.Value, KeyTime.FromPercent(0));
        var key2 = new DiscreteMatrixKeyFrame(newTransform.Value, KeyTime.FromPercent(1));

        Storyboard.SetTarget(anim, element.RenderTransform);
        Storyboard.SetTargetProperty(anim, new PropertyPath(UIElement.RenderTransformProperty));
        Storyboard sb = new Storyboard();
        sb.Children.Add(anim);
        sb.Duration = AnimationDuration;
        sb.Begin();
    }

它总是在 sb.Begin() 调用中引发异常,告诉我,我的“PropertyPath”有问题。我不知道该怎么做:(。 我的意思是,没有办法直接创建“TransformAnimation”,对吧?只有 MatrixAnimations 可用...

【问题讨论】:

    标签: c# wpf animation rendertransform


    【解决方案1】:

    我在下面提供了ScaleTransform 的简单动画。为了提供一个“最小”的例子,我只调整了比例;我不会根据鼠标位置进行任何偏移计算。你应该能够弄清楚从这里去哪里:

    private void OnMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var factor = e.Delta > 0d ? 1.1d : 0.9d;
    
        var t = mNetworkUI.RenderTransform as ScaleTransform;
        if (t == null)
        {
            mNetworkUI.RenderTransform = t = new ScaleTransform(1d, 1d)
                                             {
                                                 CenterX = 0.5d,
                                                 CenterY = 0.5d
                                             };
        }
    
        var oldScale = (double)t.GetAnimationBaseValue(ScaleTransform.ScaleXProperty);
        var newScale = oldScale * factor;
    
        //
        // Make sure `GetAnimationBaseValue()` reflects the `To` value next time
        // (needed to calculate `oldScale`, and for the animation to infer `From`).
        //
        t.ScaleX = newScale;
        t.ScaleY = newScale;
    
        var animation = new DoubleAnimation
                        {
                            To = newScale,
                            Duration = TimeSpan.FromSeconds(0.5d),
                            DecelerationRatio = 0.5d,
                            FillBehavior = FillBehavior.Stop
                        };
    
        //
        // Use `HandoffBehavior.Compose` to transition more smoothly if an animation
        // is already in progress.
        //
        t.BeginAnimation(
            ScaleTransform.ScaleXProperty, 
            animation, 
            HandoffBehavior.Compose);
    
        t.BeginAnimation(
            ScaleTransform.ScaleYProperty,
            animation,
            HandoffBehavior.Compose);
    }
    

    【讨论】:

    • 如果您解释为什么明确设置t.ScaleX = newScale,您将获得+1。这被动画覆盖了,不是吗?顺便说一句,您不需要指定oldScale。动画可以解决这个问题。
    • 是的,缩放值被动画覆盖,但仅限于动画的持续时间。动画结束后,您希望该属性仍具有 To 值。但是是的,您可以指定 just To 值或 just From 值并让动画找出另一个。
    • 为什么不将这两个动画包装在故事板中呢?否则,这对我来说似乎是正确的。
    • 你当然可以使用故事板,我通常在协调两个以上的动画时使用(尤其是当它们的时间线不相同时)。在这种情况下,我觉得它只是增加了一层复杂性。
    • 如果动画已经在进行中,则稍微调整一下答案以使事情变得顺畅。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 2012-08-15
    • 2023-02-02
    • 2010-10-07
    相关资源
    最近更新 更多