Browse Source

And Pinch gensture

pull/9751/head
Emmanuel Hansen 3 years ago
parent
commit
8e2f9d5346
  1. 131
      src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs
  2. 4
      src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs
  3. 8
      src/Avalonia.Base/Input/Gestures.cs
  4. 24
      src/Avalonia.Base/Input/PinchEventArgs.cs

131
src/Avalonia.Base/Input/GestureRecognizers/PinchGestureRecognizer.cs

@ -0,0 +1,131 @@
using Avalonia.Input.GestureRecognizers;
namespace Avalonia.Input
{
public class PinchGestureRecognizer : StyledElement, IGestureRecognizer
{
private IInputElement? _target;
private IGestureRecognizerActionsDispatcher? _actions;
private float _initialDistance;
private IPointer? _firstContact;
private Point _firstPoint;
private IPointer? _secondContact;
private Point _secondPoint;
private Point _origin;
public void Initialize(IInputElement target, IGestureRecognizerActionsDispatcher actions)
{
_target = target;
_actions = actions;
_target?.AddHandler(InputElement.PointerPressedEvent, OnPointerPressed, Interactivity.RoutingStrategies.Tunnel | Interactivity.RoutingStrategies.Bubble);
_target?.AddHandler(InputElement.PointerReleasedEvent, OnPointerReleased, Interactivity.RoutingStrategies.Tunnel | Interactivity.RoutingStrategies.Bubble);
}
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
PointerPressed(e);
}
private void OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
PointerReleased(e);
}
public void PointerCaptureLost(IPointer pointer)
{
RemoveContact(pointer);
}
public void PointerMoved(PointerEventArgs e)
{
if (_target != null && _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;
_target?.RaiseEvent(new PinchEventArgs(scale, _origin));
}
}
}
public void PointerPressed(PointerPressedEventArgs e)
{
if (_target != null && _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);
_origin = new Point((_firstPoint.X + _secondPoint.X) / 2.0f, (_firstPoint.Y + _secondPoint.Y) / 2.0f);
_actions!.Capture(_firstContact, this);
_actions!.Capture(_secondContact, this);
}
}
}
public void PointerReleased(PointerReleasedEventArgs e)
{
RemoveContact(e.Pointer);
}
private void RemoveContact(IPointer pointer)
{
if (_firstContact == pointer || _secondContact == pointer)
{
if (_secondContact == pointer)
{
_secondContact = null;
}
if (_firstContact == pointer)
{
_firstContact = _secondContact;
_secondContact = null;
}
_target?.RaiseEvent(new PinchEndedEventArgs());
}
}
private float GetDistance(Point a, Point b)
{
var length = _secondPoint - _firstPoint;
return (float)new Vector(length.X, length.Y).Length;
}
}
}

4
src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -68,7 +68,7 @@ namespace Avalonia.Input.GestureRecognizers
}
/// <summary>
/// Gets or sets a value indicating the distance to move the pointer before scrolling is started
/// Gets or sets a value indicating the distance the pointer moves before scrolling is started
/// </summary>
public int ScrollStartDistance
{
@ -96,7 +96,7 @@ namespace Avalonia.Input.GestureRecognizers
}
// Pixels per second speed that is considered to be the stop of inertial scroll
private const double InertialScrollSpeedEnd = 5;
private const double InertialScrollSpeedEnd = 0;
public void PointerMoved(PointerEventArgs e)
{

8
src/Avalonia.Base/Input/Gestures.cs

@ -46,6 +46,14 @@ namespace Avalonia.Input
private static readonly WeakReference<object?> s_lastPress = new WeakReference<object?>(null);
private static Point s_lastPressPoint;
public static readonly RoutedEvent<PinchEventArgs> PinchEvent =
RoutedEvent.Register<PinchEventArgs>(
"PinchEvent", RoutingStrategies.Bubble, typeof(Gestures));
public static readonly RoutedEvent<PinchEndedEventArgs> PinchEndedEvent =
RoutedEvent.Register<PinchEndedEventArgs>(
"PinchEndedEvent", RoutingStrategies.Bubble, typeof(Gestures));
public static readonly RoutedEvent<PullGestureEventArgs> PullGestureEvent =
RoutedEvent.Register<PullGestureEventArgs>(
"PullGesture", RoutingStrategies.Bubble, typeof(Gestures));

24
src/Avalonia.Base/Input/PinchEventArgs.cs

@ -0,0 +1,24 @@
using Avalonia.Interactivity;
namespace Avalonia.Input
{
public class PinchEventArgs : RoutedEventArgs
{
public PinchEventArgs(double scale, Point scaleOrigin) : base(Gestures.PinchEvent)
{
Scale = scale;
ScaleOrigin = scaleOrigin;
}
public double Scale { get; } = 1;
public Point ScaleOrigin { get; }
}
public class PinchEndedEventArgs : RoutedEventArgs
{
public PinchEndedEventArgs() : base(Gestures.PinchEndedEvent)
{
}
}
}
Loading…
Cancel
Save