Zoom on Canvas, centered on mouse position

后端 未结 1 512
不知归路
不知归路 2020-12-20 09:25

I know there are several posts on stack and others websites, but it seems I still make something wrong. When I zoom with MouseWheel event, the zoom is always not centered, b

相关标签:
1条回答
  • 2020-12-20 09:48

    Here is a very basic example for zooming and panning a Canvas with fixed initial size. The MatrixTransform in the RenderTransform of the inner Canvas provides the necessary transformations, while the outer Canvas handles mouse input and sets an initial scaling.

    <Canvas Background="Transparent"
            SizeChanged="ViewportSizeChanged"
            MouseLeftButtonDown="ViewportMouseLeftButtonDown"
            MouseLeftButtonUp="ViewportMouseLeftButtonUp"
            MouseMove="ViewportMouseMove"
            MouseWheel="ViewportMouseWheel">
    
        <Canvas x:Name="canvas" Width="1000" Height="600">
            <Canvas.RenderTransform>
                <MatrixTransform x:Name="transform"/>
            </Canvas.RenderTransform>
    
            <Ellipse Fill="Red" Width="100" Height="100" Canvas.Left="100" Canvas.Top="100"/>
            <Ellipse Fill="Green" Width="100" Height="100" Canvas.Right="100" Canvas.Bottom="100"/>
        </Canvas>
    </Canvas>
    

    Code behind:

    private Point? mousePos;
    
    private void ViewportSizeChanged(object sender, SizeChangedEventArgs e)
    {
        ((MatrixTransform)canvas.RenderTransform).Matrix = new Matrix(
            e.NewSize.Width / canvas.ActualWidth,
            0, 0,
            e.NewSize.Height / canvas.ActualHeight,
            0, 0);
    }
    
    private void ViewportMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var viewport = (UIElement)sender;
        viewport.CaptureMouse();
        mousePos = e.GetPosition(viewport);
    }
    
    private void ViewportMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        ((UIElement)sender).ReleaseMouseCapture();
        mousePos = null;
    }
    
    private void ViewportMouseMove(object sender, MouseEventArgs e)
    {
        if (mousePos.HasValue)
        {
            var pos = e.GetPosition((UIElement)sender);
            var matrix = transform.Matrix;
            matrix.Translate(pos.X - mousePos.Value.X, pos.Y - mousePos.Value.Y);
            transform.Matrix = matrix;
            mousePos = pos;
        }
    }
    
    private void ViewportMouseWheel(object sender, MouseWheelEventArgs e)
    {
        var pos = e.GetPosition((UIElement)sender);
        var matrix = transform.Matrix;
        var scale = e.Delta > 0 ? 1.1 : 1 / 1.1;
        matrix.ScaleAt(scale, scale, pos.X, pos.Y);
        transform.Matrix = matrix;
    }
    
    0 讨论(0)
提交回复
热议问题