XAML WPF平移图像-防止图像边缘平移出视图/边界

jk9hmnmh  于 2023-09-28  发布在  其他
关注(0)|答案(1)|浏览(171)

我使用这个项目作为参考:https://www.codeproject.com/Articles/168176/Zooming-and-panning-in-WPF-with-fixed-focus,但我想限制图像从屏幕上平移。我想平移停止在一个轴时,图像的边缘是一些固定的距离从边界的边缘。例如,图像的右边缘应始终与边框的左边缘相距至少+70。
我已经找到了一些答案和未回答的问题,但这一个似乎让我更接近:
wpf-image-panning-constraints
我修改了鼠标移动代码如下:

private void image_MouseMove(object sender, MouseEventArgs e)
    {
        if (!image.IsMouseCaptured) return;
        Point p = e.MouseDevice.GetPosition(border);

        Point relativePoint = image.TransformToAncestor(border)
                      .Transform(new Point(0, 0));

        

        Matrix m = image.RenderTransform.Value;
        var xDelta = p.X - start.X;
        var yDelta = p.Y - start.Y;
        m.OffsetX = origin.X + (xDelta);
        m.OffsetY = origin.Y + (yDelta);

        var currentImageBounds = ImageBounds();
        var relativePosition  = image.TransformToAncestor(border).Transform(new Point(0, 0));
        if (currentImageBounds.Right <= 70 && xDelta<0)
        {
            //I'm messing with this code to modify/fix the x offset  
            m.OffsetX = origin.X;//CurrentImageBounds.Left + 70 ; //+ CurrentImageBounds.Width+70;
        }
        image.RenderTransform = new MatrixTransform(m);
    }

    private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (image.IsMouseCaptured) return;
        image.CaptureMouse();

        start = e.GetPosition(border);
        origin.X = image.RenderTransform.Value.OffsetX;
        origin.Y = image.RenderTransform.Value.OffsetY;
    }

    private Rect ImageBounds()
    {
        var rect = new Rect(image.RenderSize);
        var bounds = image.TransformToAncestor(border).TransformBounds(rect);
        //CurrentImageBounds = bounds;
        Debug.WriteLine($"ImageRight: {bounds.Right}");
        return bounds;
    }

当我达到70px的阈值时,图像只是在边缘反弹。我漏掉了什么东西卡住了。

我该如何实现这一点?

uidvcgyl

uidvcgyl1#

下面是一个在Canvas中缩放和平移Image元素的简短示例。它处理画布上的鼠标事件,而不是图像上的。
看一下MouseMove事件处理程序中的代码块if (translateConstraint > 0) { ... },其中每个方向上可能的转换量都是有限的。变换后的Image元素的边界是通过使用Image#s RenderTransform中MatrixTransform的Matrix属性确定的。
必须将类似的东西添加到MouseWheel事件处理程序中。
还值得注意的是,代码不会在每次更新时重新分配Image的RenderTransform,而只是重新分配XAML中分配的MatrixTransform的Matrix属性。
XAML:

<Canvas Background="Transparent"
        MouseLeftButtonDown="CanvasMouseLeftButtonDown"
        MouseLeftButtonUp="CanvasMouseLeftButtonUp"
        MouseMove="CanvasMouseMove"
        MouseWheel="CanvasMouseWheel">
    <Image x:Name="image" Stretch="None">
        <Image.RenderTransform>
            <MatrixTransform/>
        </Image.RenderTransform>
    </Image>
</Canvas>

后面的代码:

private Point? mousePosition;
private int translateConstraint = 70;

private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var canvas = (Canvas)sender;
    if (canvas.CaptureMouse())
    {
        mousePosition = e.GetPosition(canvas);
    }
}

private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    var canvas = (Canvas)sender;
    canvas.ReleaseMouseCapture();
    mousePosition = null;
}

private void CanvasMouseMove(object sender, MouseEventArgs e)
{
    if (mousePosition.HasValue)
    {
        var canvas = (Canvas)sender;
        var p = e.GetPosition(canvas);
        var matrix = ((MatrixTransform)image.RenderTransform).Matrix;
        var dx = p.X - mousePosition.Value.X;
        var dy = p.Y - mousePosition.Value.Y;
        mousePosition = p;

        if (translateConstraint > 0)
        {
            var imageSize = new Point(image.ActualWidth, image.ActualHeight);
            var imageBounds = new Rect(
                matrix.Transform(new Point()),
                matrix.Transform(imageSize));

            var dxMin = translateConstraint - imageBounds.Right;
            var dxMax = canvas.ActualWidth - translateConstraint - imageBounds.Left;
            dx = Math.Min(Math.Max(dx, dxMin), dxMax);

            var dyMin = translateConstraint - imageBounds.Bottom;
            var dyMax = canvas.ActualHeight - translateConstraint - imageBounds.Top;
            dy = Math.Min(Math.Max(dy, dyMin), dyMax);
        }

        matrix.Translate(dx, dy);
        ((MatrixTransform)image.RenderTransform).Matrix = matrix;
    }
}

private void CanvasMouseWheel(object sender, MouseWheelEventArgs e)
{
    var canvas = (Canvas)sender;
    var p = e.GetPosition(canvas);
    var matrix = ((MatrixTransform)image.RenderTransform).Matrix;
    var scale = e.Delta >= 0 ? 1.1 : (1.0 / 1.1); // choose appropriate scaling factor

    matrix.ScaleAt(scale, scale, p.X, p.Y);
    ((MatrixTransform)image.RenderTransform).Matrix = matrix;
}

相关问题