forked from amkovkov/GranuSightSoftware2
feat: ZoomPanImage make zoom and pans public
This commit is contained in:
@@ -11,9 +11,6 @@ public class ZoomPanImage : Control
|
||||
{
|
||||
private Point? _lastMousePosition = null;
|
||||
private Dictionary<int, Point>? _lastTouchPositions = null;
|
||||
private float _zoom = 1;
|
||||
private float _panX = 0;
|
||||
private float _panY = 0;
|
||||
|
||||
public static readonly StyledProperty<Color> BackgroundProperty = AvaloniaProperty.Register<ZoomPanImage, Color>(nameof(Background), defaultValue: Colors.Transparent);
|
||||
public Color Background
|
||||
@@ -39,15 +36,33 @@ public class ZoomPanImage : Control
|
||||
get => GetValue(ImageSourceProperty);
|
||||
set => SetValue(ImageSourceProperty, value);
|
||||
}
|
||||
public static readonly StyledProperty<float> ZoomProperty = AvaloniaProperty.Register<ZoomPanImage, float>(nameof(Zoom), defaultValue: 1);
|
||||
public float Zoom
|
||||
{
|
||||
get => GetValue(ZoomProperty);
|
||||
set => SetValue(ZoomProperty, value);
|
||||
}
|
||||
public static readonly StyledProperty<float> PanXProperty = AvaloniaProperty.Register<ZoomPanImage, float>(nameof(PanX), defaultValue: 0);
|
||||
public float PanX
|
||||
{
|
||||
get => GetValue(PanXProperty);
|
||||
set => SetValue(PanXProperty, value);
|
||||
}
|
||||
public static readonly StyledProperty<float> PanYProperty = AvaloniaProperty.Register<ZoomPanImage, float>(nameof(PanY), defaultValue: 0);
|
||||
public float PanY
|
||||
{
|
||||
get => GetValue(PanYProperty);
|
||||
set => SetValue(PanYProperty, value);
|
||||
}
|
||||
|
||||
public ZoomPanImage()
|
||||
: base()
|
||||
{
|
||||
DoubleTapped += (_, _) =>
|
||||
{
|
||||
_zoom = 1f;
|
||||
_panX = 0f;
|
||||
_panY = 0f;
|
||||
Zoom = 1f;
|
||||
PanX = 0f;
|
||||
PanY = 0f;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -65,26 +80,26 @@ public class ZoomPanImage : Control
|
||||
var position = ea.GetPosition(this);
|
||||
|
||||
// Рассчитываем позицию в координатах изображения (до масштабирования)
|
||||
var imageX = (position.X - Bounds.Width / 2 - _panX) / _zoom;
|
||||
var imageY = (position.Y - Bounds.Height / 2 - _panY) / _zoom;
|
||||
var imageX = (position.X - Bounds.Width / 2 - PanX) / Zoom;
|
||||
var imageY = (position.Y - Bounds.Height / 2 - PanY) / Zoom;
|
||||
|
||||
// Применяем масштаб
|
||||
float zoomFactor = ea.Delta.Y > 0 ? 1.1f : 1 / 1.1f;
|
||||
_zoom *= zoomFactor;
|
||||
_zoom = Math.Clamp(_zoom, 1f, 10f);
|
||||
_zoom = (float)Math.Round(_zoom, 2);
|
||||
Zoom *= zoomFactor;
|
||||
Zoom = Math.Clamp(Zoom, 1f, 10f);
|
||||
Zoom = (float)Math.Round(Zoom, 2);
|
||||
|
||||
if (_zoom != 1f)
|
||||
if (Zoom != 1f)
|
||||
{
|
||||
// Пересчитываем смещение так, чтобы указатель остался на месте
|
||||
_panX = (float)(position.X - Bounds.Width / 2 - imageX * _zoom);
|
||||
_panY = (float)(position.Y - Bounds.Height / 2 - imageY * _zoom);
|
||||
PanX = (float)(position.X - Bounds.Width / 2 - imageX * Zoom);
|
||||
PanY = (float)(position.Y - Bounds.Height / 2 - imageY * Zoom);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Если зум == 1, то возвращаем изображение к исходному смещению
|
||||
_panX = 0f;
|
||||
_panY = 0f;
|
||||
PanX = 0f;
|
||||
PanY = 0f;
|
||||
}
|
||||
}
|
||||
base.OnPointerWheelChanged(ea);
|
||||
@@ -98,9 +113,9 @@ public class ZoomPanImage : Control
|
||||
{
|
||||
if (ea.ClickCount == 2) // По двойному клику возвращаем изображение к смещение и зум к стандартным значениям
|
||||
{
|
||||
_zoom = 1f;
|
||||
_panX = 0f;
|
||||
_panY = 0f;
|
||||
Zoom = 1f;
|
||||
PanX = 0f;
|
||||
PanY = 0f;
|
||||
}
|
||||
else
|
||||
_lastMousePosition = ea.GetPosition(this);
|
||||
@@ -138,14 +153,14 @@ public class ZoomPanImage : Control
|
||||
{
|
||||
if (ea.Pointer.Type == PointerType.Mouse)
|
||||
{
|
||||
if (_lastMousePosition is null || _zoom == 1) // Если кнопка не нажата или зум == 1, то ничего не делаем
|
||||
if (_lastMousePosition is null || Zoom == 1) // Если кнопка не нажата или зум == 1, то ничего не делаем
|
||||
{
|
||||
base.OnPointerMoved(ea);
|
||||
return;
|
||||
}
|
||||
var position = ea.GetPosition(this);
|
||||
_panX -= (float)(_lastMousePosition.Value.X - position.X);
|
||||
_panY -= (float)(_lastMousePosition.Value.Y - position.Y);
|
||||
PanX -= (float)(_lastMousePosition.Value.X - position.X);
|
||||
PanY -= (float)(_lastMousePosition.Value.Y - position.Y);
|
||||
_lastMousePosition = position;
|
||||
}
|
||||
else if (ea.Pointer.Type == PointerType.Touch)
|
||||
@@ -163,11 +178,11 @@ public class ZoomPanImage : Control
|
||||
return;
|
||||
}
|
||||
|
||||
if (_lastTouchPositions.Count() == 1 && _zoom != 1) // Если есть только одно прикосновение и зум != 1, то только перемещение
|
||||
if (_lastTouchPositions.Count() == 1 && Zoom != 1) // Если есть только одно прикосновение и зум != 1, то только перемещение
|
||||
{
|
||||
var position = ea.GetPosition(this);
|
||||
_panX -= (float)(_lastTouchPositions[ea.Pointer.Id].X - position.X);
|
||||
_panY -= (float)(_lastTouchPositions[ea.Pointer.Id].Y - position.Y); // Ось Y инвертирована
|
||||
PanX -= (float)(_lastTouchPositions[ea.Pointer.Id].X - position.X);
|
||||
PanY -= (float)(_lastTouchPositions[ea.Pointer.Id].Y - position.Y); // Ось Y инвертирована
|
||||
_lastTouchPositions[ea.Pointer.Id] = position;
|
||||
}
|
||||
else if (_lastTouchPositions.Count() == 2) // Если два прикосновения, то перемещение с приближением
|
||||
@@ -185,24 +200,24 @@ public class ZoomPanImage : Control
|
||||
var newCenter = PointHelper.Center(newPosition1, newPosition2);
|
||||
|
||||
var zoomFactor = newDistance / lastDistance;
|
||||
var newZoom = (float)(_zoom * zoomFactor);
|
||||
var newZoom = (float)(Zoom * zoomFactor);
|
||||
newZoom = (float)Math.Clamp(newZoom, 1f, 10f);
|
||||
|
||||
var imageX = (newCenter.X - Bounds.Width / 2 - _panX) / _zoom;
|
||||
var imageY = (newCenter.Y - Bounds.Height / 2 - _panY) / _zoom;
|
||||
var imageX = (newCenter.X - Bounds.Width / 2 - PanX) / Zoom;
|
||||
var imageY = (newCenter.Y - Bounds.Height / 2 - PanY) / Zoom;
|
||||
|
||||
_zoom = newZoom;
|
||||
Zoom = newZoom;
|
||||
|
||||
if (_zoom > 1f)
|
||||
if (Zoom > 1f)
|
||||
{
|
||||
_panX = (float)(newCenter.X - Bounds.Width / 2 - imageX * _zoom);
|
||||
_panY = (float)(newCenter.Y - Bounds.Height / 2 - imageY * _zoom);
|
||||
PanX = (float)(newCenter.X - Bounds.Width / 2 - imageX * Zoom);
|
||||
PanY = (float)(newCenter.Y - Bounds.Height / 2 - imageY * Zoom);
|
||||
}
|
||||
else
|
||||
{
|
||||
_zoom = 1f;
|
||||
_panX = 0f;
|
||||
_panY = 0f;
|
||||
Zoom = 1f;
|
||||
PanX = 0f;
|
||||
PanY = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,14 +237,14 @@ public class ZoomPanImage : Control
|
||||
}
|
||||
|
||||
var (sx, sy) = ComputeStretchScale(StretchMode, ImageSource.Size.Width, ImageSource.Size.Height);
|
||||
sx *= _zoom;
|
||||
sy *= _zoom;
|
||||
sx *= Zoom;
|
||||
sy *= Zoom;
|
||||
|
||||
var drawWidth = ImageSource.Size.Width * sx;
|
||||
var drawHeight = ImageSource.Size.Height * sy;
|
||||
var destRect = new Rect(
|
||||
(Bounds.Width - drawWidth) / 2 + _panX,
|
||||
(Bounds.Height - drawHeight) / 2 + _panY,
|
||||
(Bounds.Width - drawWidth) / 2 + PanX,
|
||||
(Bounds.Height - drawHeight) / 2 + PanY,
|
||||
drawWidth, drawHeight
|
||||
);
|
||||
|
||||
@@ -299,4 +314,4 @@ public class ZoomPanImage : Control
|
||||
return new Rect(0, 0, imageWidth, imageHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user