像Expression Blend一样实现缩放

时间:2012-01-17 15:26:56

标签: c# wpf zoom transform scale

在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;
    }

1 个答案:

答案 0 :(得分:2)

这种缩放很好,所以我试图实现它一次,它的数学有点奇怪,我花了大约两天的时间来找出有用的东西,但这可能是相当难看的代码(变量带{ {1}}是缩放控件上的字段:

_

变换的顺序当然很重要:

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();