using System; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Shapes; using Avalonia.Input; using Avalonia.Media; namespace DispenserUI.Views.Controls; public class ROISelector : Canvas { public static readonly StyledProperty ROICenterProperty = AvaloniaProperty.Register(nameof(ROICenter)); private Path centerPath; private EllipseGeometry circle; private Point circleCenter; private Path circlePath; private Point currentPoint; private bool isDragging; private bool isMouseDragged; private bool isDrawingComplete; private bool isPositionChangeable; private bool isRadiusChangeable; public Point ROICenter { get => GetValue(ROICenterProperty); set => SetValue(ROICenterProperty, value); } public ROISelector() { this.GetObservable(ROICenterProperty).Subscribe(val => { DrawROI(); }); } private double Get2PointsDistance(Point firstPoint, Point secondPoint) { return Math.Pow(Math.Pow(secondPoint.X - firstPoint.X, 2) + Math.Pow(secondPoint.Y - firstPoint.Y, 2), 0.5); } public new void OnPointerPressed(PointerPressedEventArgs e) { var pointerPoint = e.GetCurrentPoint(this); //鼠标左键按下 if (pointerPoint.Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed) { isDragging = true; //开启拖动 //未绘制ROI区域,可以开始绘制 if (isDrawingComplete == false) { circleCenter = e.GetPosition(this); } //已经绘制ROI区域,可以修改区域 else { currentPoint = e.GetPosition(this); var distance = Get2PointsDistance(currentPoint, circleCenter); //点击圆内位置,移动圆位置 if (distance < circle.RadiusX) isPositionChangeable = true; //点击圆外30像素以内位置,改变圆半径 else if (distance > circle.RadiusX && distance < circle.RadiusX + 30) isRadiusChangeable = true; } } e.Handled = false; } public new void OnPointerReleased(PointerReleasedEventArgs e) { var pointerPoint = e.GetCurrentPoint(this); // 鼠标左键释放:结束绘制 if (pointerPoint.Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonReleased) { isDragging = false; //结束拖动 if (isMouseDragged == true) { isDrawingComplete = true; //绘制完成 isMouseDragged = false; } isRadiusChangeable = false; isPositionChangeable = false; } //鼠标右键释放:确定数据,清除图像 else if (pointerPoint.Properties.PointerUpdateKind == PointerUpdateKind.RightButtonReleased) { isPositionChangeable = false; isRadiusChangeable = false; isDrawingComplete = false; Children.Remove(circlePath); ROICenter = new Point(circleCenter.X, circleCenter.Y); } e.Handled = false; } public new void OnPointerMoved(PointerEventArgs e) { if (isDragging == false) return; isMouseDragged = true; currentPoint = e.GetPosition(this); DrawROI(); e.Handled = false; } private void DrawROI() { Children.Remove(circlePath); Children.Remove(centerPath); //绘制ROI if (isDrawingComplete == false) { var radius = Get2PointsDistance(currentPoint, circleCenter); DrawCircle(circleCenter, radius); } else if (isPositionChangeable) { var radius = circle.RadiusX; circleCenter = currentPoint; DrawCircle(circleCenter, radius); } else if (isRadiusChangeable) { var radius = Get2PointsDistance(currentPoint, circleCenter); DrawCircle(circleCenter, radius); } Children.Add(circlePath); Children.Add(centerPath); } private void DrawCircle(Point center, double radius) { circle = new EllipseGeometry { Center = center, RadiusX = radius, RadiusY = radius }; circlePath = new Path { Data = circle, Stroke = Brushes.Orange, StrokeThickness = 2 }; var centerPoint = new EllipseGeometry { Center = center, RadiusX = 2, RadiusY = 2, }; centerPath = new Path { Data = centerPoint, Stroke = Brushes.Orange, Fill = Brushes.Orange, StrokeThickness = 2 }; } }