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