123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- using Avalonia;
- using Avalonia.Input;
- using Avalonia.Input.GestureRecognizers;
- using Avalonia.Interactivity;
- namespace InABox.Avalonia.Components.ImageEditing;
- public class PanAndZoomEventArgs : RoutedEventArgs
- {
- public PanAndZoomEventArgs(double scale, Point scaleOrigin, Vector pan) : base(PanAndZoomGestureRecognizer.PanAndZoomEvent)
- {
- Scale = scale;
- ScaleOrigin = scaleOrigin;
- Pan = pan;
- }
- public double Scale { get; } = 1;
- public Point ScaleOrigin { get; }
- public Vector Pan { get; set; }
- }
- public class PanAndZoomEndedEventArgs : RoutedEventArgs
- {
- public PanAndZoomEndedEventArgs() : base(PanAndZoomGestureRecognizer.PanAndZoomEndedEvent)
- {
- }
- }
- // Adapted from the PinchGestureRecognizer built in to Avalonia, but with panning added.
- public class PanAndZoomGestureRecognizer : GestureRecognizer
- {
- public static readonly RoutedEvent<PanAndZoomEventArgs> PanAndZoomEvent =
- RoutedEvent.Register<PanAndZoomEventArgs>(
- "PanAndZoom", RoutingStrategies.Bubble, typeof(PanAndZoomGestureRecognizer));
- public static readonly RoutedEvent<PanAndZoomEndedEventArgs> PanAndZoomEndedEvent =
- RoutedEvent.Register<PanAndZoomEndedEventArgs>(
- "PanAndZoomEnded", RoutingStrategies.Bubble, typeof(PanAndZoomGestureRecognizer));
- private float _initialDistance;
- private IPointer? _firstContact;
- private Point _firstPoint;
- private IPointer? _secondContact;
- private Point _secondPoint;
- private Point _previousOrigin;
- protected override void PointerCaptureLost(IPointer pointer)
- {
- RemoveContact(pointer);
- }
- protected override void PointerMoved(PointerEventArgs e)
- {
- if (Target is Visual visual)
- {
- if (_firstContact == e.Pointer)
- {
- _firstPoint = e.GetPosition(visual);
- }
- else if (_secondContact == e.Pointer)
- {
- _secondPoint = e.GetPosition(visual);
- }
- else
- {
- return;
- }
- if (_firstContact != null && _secondContact != null)
- {
- var distance = GetDistance(_firstPoint, _secondPoint);
- var scale = distance / _initialDistance;
- var origin = (_firstPoint + _secondPoint) / 2;
- var pinchEventArgs = new PanAndZoomEventArgs(scale, origin, origin - _previousOrigin);
- _previousOrigin = origin;
- Target?.RaiseEvent(pinchEventArgs);
- e.Handled = pinchEventArgs.Handled;
- e.PreventGestureRecognition();
- }
- }
- }
- protected override void PointerPressed(PointerPressedEventArgs e)
- {
- if (Target is Visual visual && (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen))
- {
- if (_firstContact == null)
- {
- _firstContact = e.Pointer;
- _firstPoint = e.GetPosition(visual);
- return;
- }
- else if (_secondContact == null && _firstContact != e.Pointer)
- {
- _secondContact = e.Pointer;
- _secondPoint = e.GetPosition(visual);
- }
- else
- {
- return;
- }
- if (_firstContact != null && _secondContact != null)
- {
- _initialDistance = GetDistance(_firstPoint, _secondPoint);
- _previousOrigin = new Point((_firstPoint.X + _secondPoint.X) / 2.0f, (_firstPoint.Y + _secondPoint.Y) / 2.0f);
- Capture(_firstContact);
- Capture(_secondContact);
- e.PreventGestureRecognition();
- }
- }
- }
- protected override void PointerReleased(PointerReleasedEventArgs e)
- {
- if(RemoveContact(e.Pointer))
- {
- e.PreventGestureRecognition();
- }
- }
- private bool RemoveContact(IPointer pointer)
- {
- if (_firstContact == pointer || _secondContact == pointer)
- {
- if (_secondContact == pointer)
- {
- _secondContact = null;
- }
- if (_firstContact == pointer)
- {
- _firstContact = _secondContact;
- _secondContact = null;
- }
- Target?.RaiseEvent(new PanAndZoomEndedEventArgs());
- return true;
- }
- return false;
- }
- private static float GetDistance(Point a, Point b)
- {
- var length = b - a;
- return (float)new Vector(length.X, length.Y).Length;
- }
- }
|