将画布缩放到鼠标位置

时间:2014-03-12 11:22:42

标签: c# wpf

我正在尝试使用鼠标滚轮为画布实现缩放功能。 目前我只是使用CenterX =“0.5”和CenterY =“0.5”缩放到画布的中心位置。 我想改变行为,以便在鼠标位置进行缩放,我想知道是否可以使用ScaleTransform。

目前我使用以下代码:

<Canvas Width="500" Height="500">
    <Canvas.LayoutTransform>
        <ScaleTransform CenterX="0.5" CenterY="0.5"
                                ScaleX="{Binding Zoom}"
                                ScaleY="{Binding Zoom}" />
    </Canvas.LayoutTransform>
</Canvas>

2 个答案:

答案 0 :(得分:11)

在特定位置缩放Canvas(或任何其他UIElement)的一种非常基本的方法是使用MatrixTransform作为RenderTransform属性

<Canvas Width="500" Height="500" MouseWheel="Canvas_MouseWheel">
    <Canvas.RenderTransform>
        <MatrixTransform/>
    </Canvas.RenderTransform>
</Canvas>

并更新变换的Matrix属性,就像在这个MouseWheel处理程序中一样:

private void Canvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
    var element = sender as UIElement;
    var position = e.GetPosition(element);
    var transform = element.RenderTransform as MatrixTransform;
    var matrix = transform.Matrix;
    var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); // choose appropriate scaling factor

    matrix.ScaleAtPrepend(scale, scale, position.X, position.Y);
    transform.Matrix = matrix;
}

答案 1 :(得分:2)

过去两天我在这个问题上苦苦挣扎,我想出来了。这将使您平滑地放大鼠标并平滑缩小。我在这里发布我的解决方案给那些可能会在这里搜索和绊倒的人。

// Class constructor
public YourClass(Canvas theCanvas) //You may not need the Canvas as an argument depending on your scope
    {
        panTransform = new TranslateTransform();
        zoomTransform = new ScaleTransform();
        bothTransforms = new TransformGroup();

        bothTransforms.Children.Add(panTransform);
        bothTransforms.Children.Add(zoomTransform);

        theCanvas.RenderTransform = bothTransforms;

        //Handler
        theCanvas.MouseWheel += wheelEvent;
        //You also need your own handlers for panning, which I'm not showing here.
    }

private void returnCalculatedScale()
    {
        double d;
        //Do some math to get a new scale. I keep track of an integer, and run it through the formula y^(x/3) where X is the integer.

        return d;
    }


// Mouse wheel handler, where the magic happens
private void wheelEvent(object sender, MouseWheelEventArgs e)
    {
        Point position = e.GetPosition(mainCanvas);           

        zoomTransform.CenterX = position.X;
        zoomTransform.CenterY = position.Y;

        zoomTransform.ScaleX = returnCalculatedScale();
        zoomTransform.ScaleY = returnCalculatedScale();

        Point cursorpos = Mouse.GetPosition(mainCanvas); //This was the secret, as the mouse position gets out of whack when the transform occurs, but Mouse.GetPosition lets us get the point accurate to the transformed canvas.

        double discrepancyX = cursorpos.X - position.X;
        double discrepancyY = cursorpos.Y - position.Y;

        //If your canvas is already panned an arbitrary amount, this aggregates the discrepancy to the TranslateTransform.
        panTransform.X += discrepancyX;
        panTransform.Y += discrepancyY;