From b5a6c360b1b5e5b36f0014d668e45baee989741c Mon Sep 17 00:00:00 2001 From: Samuel Mannehed Date: Sun, 3 Mar 2024 01:35:27 +0100 Subject: [PATCH] Allow very small twodrag and pinch gestures Before this commit, we strictly required the user to make a ~50 pixel move in order to get these two gestures. We can get a more precise experience if we allow very small gestures as well. This can be achieved by making better use of our "_twoTouchTimeout". Our two touch timeout handling was written to handle this well anyway. We can distinguish between drag and pinch using the angle. --- core/input/gesturehandler.js | 25 +++++++++++++------------ tests/test.gesturehandler.js | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/core/input/gesturehandler.js b/core/input/gesturehandler.js index 6fa72d2aa..edd1205d2 100644 --- a/core/input/gesturehandler.js +++ b/core/input/gesturehandler.js @@ -186,14 +186,14 @@ export default class GestureHandler { } if (!this._hasDetectedGesture()) { - // Ignore moves smaller than the minimum threshold - if (Math.hypot(deltaX, deltaY) < GH_MOVE_THRESHOLD) { - return; - } - // Can't be a tap or long press as we've seen movement - this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS); - this._stopLongpressTimeout(); + let deltaMove = Math.hypot(deltaX, deltaY); + + // Can't be a tap or long press if we've seen movement + if (deltaMove >= GH_MOVE_THRESHOLD) { + this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS); + this._stopLongpressTimeout(); + } if (this._tracked.length !== 1) { this._state &= ~(GH_DRAG); @@ -213,10 +213,10 @@ export default class GestureHandler { let prevDeltaMove = Math.hypot(prevTouch.firstX - prevTouch.lastX, prevTouch.firstY - prevTouch.lastY); - // We know that the current touch moved far enough, - // but unless both touches moved further than their - // threshold we don't want to disqualify any gestures - if (prevDeltaMove > GH_MOVE_THRESHOLD) { + // Unless both touches moved further than their threshold we + // don't want to disqualify any gestures right now + if (deltaMove > GH_MOVE_THRESHOLD && + prevDeltaMove > GH_MOVE_THRESHOLD) { // The angle difference between the direction of the touch points let deltaAngle = Math.abs(touch.angle - prevTouch.angle); @@ -234,7 +234,8 @@ export default class GestureHandler { } } else if (!this._isTwoTouchTimeoutRunning()) { // We can't determine the gesture right now, let's - // wait and see if more events are on their way + // wait and see if more events are on their way. + // If not, we'll have to decide which gesture it is. this._startTwoTouchTimeout(); } } diff --git a/tests/test.gesturehandler.js b/tests/test.gesturehandler.js index 73356be36..917f995e4 100644 --- a/tests/test.gesturehandler.js +++ b/tests/test.gesturehandler.js @@ -582,7 +582,7 @@ describe('Gesture handler', function () { touchStart(1, 50.0, 40.0); touchStart(2, 60.0, 40.0); touchMove(1, 80.0, 40.0); - touchMove(2, 110.0, 40.0); + touchMove(2, 90.0, 40.0); expect(gestures).to.not.have.been.called; @@ -603,7 +603,7 @@ describe('Gesture handler', function () { detail: { type: 'twodrag', clientX: 55.0, clientY: 40.0, - magnitudeX: 40.0, + magnitudeX: 30.0, magnitudeY: 0.0 } })); }); @@ -611,7 +611,7 @@ describe('Gesture handler', function () { touchStart(1, 40.0, 40.0); touchStart(2, 40.0, 60.0); touchMove(2, 40.0, 80.0); - touchMove(1, 40.0, 100.0); + touchMove(1, 40.0, 80.0); expect(gestures).to.not.have.been.called; @@ -633,14 +633,14 @@ describe('Gesture handler', function () { clientX: 40.0, clientY: 50.0, magnitudeX: 0.0, - magnitudeY: 40.0 } })); + magnitudeY: 30.0 } })); }); it('should handle slow diagonal two finger drag', function () { touchStart(1, 50.0, 40.0); touchStart(2, 40.0, 60.0); touchMove(1, 70.0, 60.0); - touchMove(2, 90.0, 110.0); + touchMove(2, 60.0, 80.0); expect(gestures).to.not.have.been.called; @@ -661,8 +661,8 @@ describe('Gesture handler', function () { detail: { type: 'twodrag', clientX: 45.0, clientY: 50.0, - magnitudeX: 35.0, - magnitudeY: 35.0 } })); + magnitudeX: 20.0, + magnitudeY: 20.0 } })); }); it('should ignore too slow two finger drag', function () { @@ -785,7 +785,7 @@ describe('Gesture handler', function () { it('should handle pinching inwards slowly', function () { touchStart(1, 0.0, 0.0); touchStart(2, 130.0, 130.0); - touchMove(1, 50.0, 40.0); + touchMove(1, 30.0, 20.0); touchMove(2, 100.0, 130.0); expect(gestures).to.not.have.been.called; @@ -807,14 +807,14 @@ describe('Gesture handler', function () { detail: { type: 'pinch', clientX: 65.0, clientY: 65.0, - magnitudeX: 50.0, - magnitudeY: 90.0 } })); + magnitudeX: 70.0, + magnitudeY: 110.0 } })); }); it('should handle pinching outwards slowly', function () { touchStart(1, 100.0, 130.0); touchStart(2, 110.0, 130.0); - touchMove(2, 200.0, 130.0); + touchMove(2, 130.0, 130.0); expect(gestures).to.not.have.been.called; @@ -835,7 +835,7 @@ describe('Gesture handler', function () { detail: { type: 'pinch', clientX: 105.0, clientY: 130.0, - magnitudeX: 100.0, + magnitudeX: 30.0, magnitudeY: 0.0 } })); });