【问题标题】:Implement a zoom as in Expression Blend在 Expression Blend 中实现缩放
【发布时间】:2012-02-12 09:49:59
【问题描述】:

在 Expression Blend 中,当您滚动鼠标滚轮时,屏幕上的元素会放大/缩小,并聚焦在鼠标所在的位置。

我正在尝试在我自己的项目中实现相同的缩放,但是在缩放、移动鼠标​​然后再次缩放后它会跳来跳去。

到目前为止,我正在使用带有 ScaleTransform 的 RenderTransform,使用鼠标坐标作为 ScaleTransform 的 centerX 和 centerY。

有人知道他们是如何在 Expression Blend 中做到的吗?

这是我到目前为止所做的:

    private void ScrollCanvasMouseWheel(object sender, MouseWheelEventArgs e)
    {
        double zoomAmnt = e.Delta > 0 ? 0.2 : -0.2;
        _scaleTransformAmount += zoomAmnt;

        if (_scaleTransformAmount < 0.5)
            _scaleTransformAmount = 0.5;

        Point position = e.GetPosition(ScrollCanvas);

        var scaleTransform = ScrollCanvas.RenderTransform as ScaleTransform;
        if (scaleTransform == null) throw new ArgumentNullException("scaleTransform");

        scaleTransform.ScaleX = _scaleTransformAmount;
        scaleTransform.ScaleY = _scaleTransformAmount;
        scaleTransform.CenterX = position.X;
        scaleTransform.CenterY = position.Y;
    }

【问题讨论】:

    标签: c# wpf zooming transform scale


    【解决方案1】:

    这种缩放很好,所以我尝试实现一次,它的数学有点奇怪,我花了大约两天时间才弄清楚可行的方法,虽然这可能是相当丑陋的代码(带有@的变量987654321@ 是缩放控件上的字段):

    Point cursorPos = e.GetPosition(this);
    Point newCenter = _scaleT.Inverse.Transform(_translateT.Inverse.Transform(cursorPos));
    Point oldCenter = new Point(_scaleT.CenterX, _scaleT.CenterY);
    Vector oldToNewCenter = newCenter - oldCenter;
    _scaleT.CenterX = newCenter.X;
    _scaleT.CenterY = newCenter.Y;
    _translateT.X += oldToNewCenter.X * (_scaleT.ScaleX - 1.0);
    _translateT.Y += oldToNewCenter.Y * (_scaleT.ScaleY - 1.0);
    
    _scalingAnimation.From = _scaleT.ScaleX;
    if (e.Delta > 0)
    {
        _scalingAnimation.To = _scaleT.ScaleX * ZoomScaleChangeFactor;
    }
    else
    {
        _scalingAnimation.To = _scaleT.ScaleX / ZoomScaleChangeFactor;
    }
    _scaleT.BeginAnimation(ScaleTransform.ScaleXProperty, _scalingAnimation);
    _scaleT.BeginAnimation(ScaleTransform.ScaleYProperty, _scalingAnimation);
    
    this.ReleaseMouseCapture();
    

    转换的顺序当然很重要:

    TransformGroup tGroup = new TransformGroup();
    tGroup.Children.Add(_scaleT);
    tGroup.Children.Add(_translateT);
    

    【讨论】:

    • 好的,这与我想象的尝试完全不同,但我会试一试! _scalingAnimation 字段是什么类型的?
    • 别担心,我将其设为DoubleAnimation,这似乎有效。至于整体效果,和我想要的差不多,但不完全。我发现您不能真正放大到一半,然后非常有效地将缩放“焦点”切换到不同的区域;它朝正确的方向移动得如此轻微,但过了一会儿我的焦点离开了屏幕。
    • 真的吗?这从来没有发生在我身上,也许你从不同的控件而不是应用转换的控件中得到了点?
    • 我不认为我可以厚颜无耻地要求一个 *.xaml / *.cs 文件对,这是一个“完整”的解决方案,就像你看到的那样,我认为问题可能是与我对上述代码的实现有关。
    • 我刚刚对它进行了更广泛的测试,结果证明你是对的,有一个漂移问题。我不知道如何摆脱它...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多