26 private readonly Dictionary<int, Point> _activePoints =
new();
27 private double _startingDistance;
28 private double _lastDistance = 0;
29 private bool _isDisposed;
55 _touchInput = touchInput ??
throw new ArgumentNullException(nameof(touchInput));
56 _touchInput.TouchBegan += OnTouchBegan;
57 _touchInput.TouchMoved += OnTouchMoved;
58 _touchInput.TouchEnded += OnTouchEnded;
63 var prevCount = _activePoints.Count;
69 var newCount = _activePoints.Count;
71 if (prevCount != 2 && newCount == 2)
73 else if (newCount != 2)
79 if (!_activePoints.ContainsKey(e.
Touch.Id))
85 if (_activePoints.Count == 2 && _lastDistance > 0)
87 var currentDistance = GetCurrentDistance();
89 if (currentDistance > 0)
94 _lastDistance = currentDistance;
98 private void OnTouchEnded(
object? sender, TouchEventArgs e)
100 var prevCount = _activePoints.Count;
102 if (_activePoints.ContainsKey(e.Touch.Id))
103 _activePoints[e.Touch.Id] = e.Touch.Position;
108 _activePoints.Remove(e.Touch.Id);
109 var newCount = _activePoints.Count;
111 if (prevCount != 2 && newCount == 2)
113 else if (newCount < 2)
117 private void BeginPinch()
119 _startingDistance = GetCurrentDistance();
120 _lastDistance = _startingDistance;
124 private void ClearBaseline()
126 _startingDistance = 0;
131 EventHandler<PinchedEventArgs>? handler,
132 double? currentDistance =
null)
134 if (_activePoints.Count != 2)
137 var pair = _activePoints.OrderBy(kvp => kvp.Key).Take(2).ToArray();
138 var a = pair[0].Value;
139 var b = pair[1].Value;
140 var distance = currentDistance ?? GetDistance(a, b);
141 var center =
new PointF((a.X + b.X) / 2f, (a.Y + b.Y) / 2f);
143 handler?.Invoke(
this,
new PinchedEventArgs(phase,
144 new[] { pair[0].Key, pair[1].Key },
151 private double GetCurrentDistance()
153 using var enumerator = _activePoints.Values.GetEnumerator();
154 if (!enumerator.MoveNext())
157 var a = enumerator.Current;
159 if (!enumerator.MoveNext())
162 var b = enumerator.Current;
164 return GetDistance(a, b);
167 private static double GetDistance(Point a, Point b)
171 return Math.Sqrt(dx * dx + dy * dy);
180 if (_isDisposed)
return;
183 _touchInput.TouchBegan -= OnTouchBegan;
184 _touchInput.TouchMoved -= OnTouchMoved;
185 _touchInput.TouchEnded -= OnTouchEnded;
189 internal void Reset()
191 _activePoints.Clear();