Avalonia 可视化图形坐标和鼠标位置通用转换方法

Avalonia 可视化图形坐标和鼠标位置通用转换方法

零、前言与示例场景

在进行一些画布编辑的应用开发的时候,获得控件的相对位置是一个很重要的点。
本文希望能够介绍一些获得控件位置的办法,供各位参考一二。

测试场景如下,在画布上的(50,50)处有一个尺寸为(100,100)的橙色矩形,其中画布具有 10 的边距:

具体的布局内容如下:

<UserControl
    x:Class="MyAvaloniaTestArea.Views.MainView"
    xmlns="https://github.com/avaloniaui"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:MyAvaloniaTestArea.ViewModels"
    d:DesignHeight="450"
    d:DesignWidth="800"
    x:DataType="vm:MainViewModel"
    Background="Gray"
    mc:Ignorable="d">
    <Design.DataContext>
        <!--
            This only sets the DataContext for the previewer in an IDE,
            to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs)
        -->
        <vm:MainViewModel />
    </Design.DataContext>

    <Canvas
        Name="PART_Canvas"
        Margin="10"
        Background="White">
        <Rectangle
            Name="PART_Rectangle"
            Canvas.Left="50"
            Canvas.Top="50"
            Width="100"
            Height="100"
            Fill="Orange" />
    </Canvas>

</UserControl>

一、鼠标相关事件在对应控件上时,事件中获得的坐标是相对于控件的

本人依次点击了矩形的四个角落,得到了以下的输出:

rectangle pointer pressed 6, 7
rectangle pointer pressed 7, 87
rectangle pointer pressed 86, 87
rectangle pointer pressed 90, 5

具体测试的代码如下:

<Rectangle
    Name="PART_Rectangle"
    Canvas.Left="50"
    Canvas.Top="50"
    Width="100"
    Height="100"
    Fill="Orange"
    PointerPressed="Rectangle_PointerPressed" />
private void Rectangle_PointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e)
{
    var rectangle = sender as Rectangle;
    var currentPointer = e.GetCurrentPoint(rectangle);
    Debug.WriteLine($"rectangle pointer pressed {currentPointer.Position}");
}

用处:可以在实现图形的拖拽时,提前保留图形拖拽点的位置,在进行移动的时候,保证鼠标能够一直抓住拖拽的起点,不至于在移动时突然鼠标抓住的点变成图形的左上角。

二、调用 GetCurrentPoint() 时传入不同的参考对象,会得到给予对应参考对象的相对坐标

private void Rectangle_PointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e)
{
    var currentPointer = e.GetCurrentPoint(PART_Canvas);
    Debug.WriteLine($"canvas pointer pressed {currentPointer.Position}");
}
canvas pointer pressed 57, 61
canvas pointer pressed 57, 135
canvas pointer pressed 135, 136
canvas pointer pressed 136, 64

用处:画布很适合当一个固定参考系,在进行一些画布处理的时候,即使当前事件并不是由画布移动触发的,还是能够更方便的拿到当前鼠标在画布的位置,用来做一些后续处理,比如点击此处在画布上创建图形等场景会有作用。

三、使用扩展方法 TranslatePoint() 进行参考系的转换

// 矩形的左上角在画布的哪个位置?
var pointBasedOnCanvas = PART_Rectangle.TranslatePoint(new Point(), PART_Canvas);
Debug.WriteLine($"point base on canvas {pointBasedOnCanvas}");
point base on canvas 50, 50

你可以看到,即使使用的是 Canvas.Left 和 Canvas.Top 进行了对图形的修改,但是实际上使用 TranslatePoint() 也可以忠实反应出图形的位置。

用处:一个很兼容的方法,系统自带的相对转换比自己写轮子要可靠。

posted @ 2025-02-24 16:16  fanbal  阅读(192)  评论(0)    收藏  举报