【问题标题】:ScaleTransform within a canvas: Centering around mouse pointer causing issues画布内的 ScaleTransform:以鼠标指针为中心导致问题
【发布时间】:2020-07-25 04:29:28
【问题描述】:

我在画布 (InnerCanvas) 中有一个画布 (OuterCanvas),并且正在按如下方式处理放大和缩小:

private ScaleTransform ScaleTransform = new ScaleTransform();

private void OuterCanvas_MouseWheel(Object sender, MouseWheelEventArgs e)
{
    if (e.Delta >= 1)
    {
        ScaleTransform.ScaleX += 0.03;
        ScaleTransform.ScaleY += 0.03;
    }
    else
    {
        ScaleTransform.ScaleX -= 0.03;
        ScaleTransform.ScaleY -= 0.03;
    }
    ScaleTransform.CenterX = ActualWidth / 2;
    ScaleTransform.CenterY = ActualHeight / 2;
    InnerCanvas.RenderTransform = TransformGroup;
}

这在画布的中心可以很好地放大和缩小。我想围绕鼠标指针进行放大和缩小,因此将CenterXCenterY 行更改如下:

ScaleTransform.CenterX = e.GetPosition(this).X;
ScaleTransform.CenterY = e.GetPosition(this).Y;

这再次令人满意,但是如果我尝试在两个缩放事件(鼠标滚轮事件)期间移动鼠标,整个画布会随着比例因子的增加或减少而剧烈地跳跃。

Demonstration of problem

这与将CenterXCenterY 属性设置为ActualWidth/2ActualHeight/2 并更改窗口大小时的问题相同。

应该如何正确处理CenterXCenterY 属性以避免此问题?

【问题讨论】:

  • 解决这个问题的一种方法是制作一个随时间平滑变化的动画。
  • 谢谢,是的,我确实计划添加动画,但我宁愿解决根本问题,而不是让不正确的过渡看起来很平滑。

标签: c# wpf canvas scaletransform


【解决方案1】:

这是一个或多或少完整的解决方案,包括平移内部 Canvas 的可能性:

<Canvas x:Name="outerCanvas"
        MouseWheel="OnMouseWheel"
        MouseMove="OnMouseMove"
        MouseLeftButtonDown="OnMouseLeftButtonDown"
        MouseLeftButtonUp="OnMouseLeftButtonUp">
    <Canvas x:Name="innerCanvas"
            Width="400" Height="400" Background="AliceBlue">
        <Canvas.RenderTransform>
            <MatrixTransform />
        </Canvas.RenderTransform>
    </Canvas>
</Canvas>

使用这些事件处理程序:

private double zoomScaleFactor = 1.1;
private Point? mousePos;

private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
    var pos = e.GetPosition(outerCanvas);
    var scale = e.Delta > 0 ? zoomScaleFactor : 1 / zoomScaleFactor;
    var transform = (MatrixTransform)innerCanvas.RenderTransform;
    var matrix = transform.Matrix;
    matrix.ScaleAt(scale, scale, pos.X, pos.Y);
    transform.Matrix = matrix;
}

private void OnMouseMove(object sender, MouseEventArgs e)
{
    if (mousePos.HasValue)
    {
        var pos = e.GetPosition(outerCanvas);
        var delta = pos - mousePos.Value;
        var transform = (MatrixTransform)innerCanvas.RenderTransform;
        var matrix = transform.Matrix;
        matrix.Translate(delta.X, delta.Y);
        transform.Matrix = matrix;
        mousePos = pos;
    }
}

private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (outerCanvas.CaptureMouse())
    {
        mousePos = e.GetPosition(outerCanvas);
    }
}

private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    outerCanvas.ReleaseMouseCapture();
    mousePos = null;
}

【讨论】:

  • 完美——这正是我的目标,但为了这个问题,我们去掉了平移。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 1970-01-01
  • 2011-07-07
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 2014-05-29
相关资源
最近更新 更多