react-native-gesture-handler 2.6.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -2
- package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/RNGestureHandler.xcodeproj/project.xcworkspace/xcuserdata/jakubpiasecki.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/RNGestureHandler.xcodeproj/xcuserdata/jakubpiasecki.xcuserdatad/xcschemes/xcschememanagement.plist +19 -0
- package/lib/commonjs/EnableExperimentalWebImplementation.js +7 -0
- package/lib/commonjs/EnableExperimentalWebImplementation.js.map +1 -1
- package/lib/commonjs/RNGestureHandlerModule.js +1 -1
- package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/RNGestureHandlerModule.macos.js +20 -9
- package/lib/commonjs/RNGestureHandlerModule.macos.js.map +1 -1
- package/lib/commonjs/RNGestureHandlerModule.web.js +23 -10
- package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/commonjs/components/GestureComponents.web.js +1 -1
- package/lib/commonjs/components/GestureComponents.web.js.map +1 -1
- package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js +1 -5
- package/lib/commonjs/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js +1 -5
- package/lib/commonjs/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/commonjs/handlers/gestures/eventReceiver.js +14 -20
- package/lib/commonjs/handlers/gestures/eventReceiver.js.map +1 -1
- package/lib/commonjs/handlers/gestures/gestureStateManager.web.js +32 -0
- package/lib/commonjs/handlers/gestures/gestureStateManager.web.js.map +1 -0
- package/lib/commonjs/web/detectors/RotationGestureDetector.js +13 -17
- package/lib/commonjs/web/detectors/RotationGestureDetector.js.map +1 -1
- package/lib/commonjs/web/detectors/ScaleGestureDetector.js +3 -14
- package/lib/commonjs/web/detectors/ScaleGestureDetector.js.map +1 -1
- package/lib/commonjs/web/handlers/FlingGestureHandler.js +37 -12
- package/lib/commonjs/web/handlers/FlingGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/GestureHandler.js +282 -79
- package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js +23 -18
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/ManualGestureHandler.js +51 -0
- package/lib/commonjs/web/handlers/ManualGestureHandler.js.map +1 -0
- package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +81 -22
- package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PanGestureHandler.js +57 -40
- package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/PinchGestureHandler.js +43 -34
- package/lib/commonjs/web/handlers/PinchGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/RotationGestureHandler.js +45 -39
- package/lib/commonjs/web/handlers/RotationGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/TapGestureHandler.js +52 -50
- package/lib/commonjs/web/handlers/TapGestureHandler.js.map +1 -1
- package/lib/commonjs/web/interfaces.js +22 -1
- package/lib/commonjs/web/interfaces.js.map +1 -1
- package/lib/commonjs/web/tools/EventManager.js +40 -96
- package/lib/commonjs/web/tools/EventManager.js.map +1 -1
- package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +109 -30
- package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
- package/lib/commonjs/web/tools/InteractionManager.js +24 -10
- package/lib/commonjs/web/tools/InteractionManager.js.map +1 -1
- package/lib/commonjs/web/tools/NodeManager.js.map +1 -1
- package/lib/commonjs/web/tools/PointerEventManager.js +130 -0
- package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -0
- package/lib/commonjs/web/tools/PointerTracker.js +97 -7
- package/lib/commonjs/web/tools/PointerTracker.js.map +1 -1
- package/lib/commonjs/web/tools/TouchEventManager.js +138 -0
- package/lib/commonjs/web/tools/TouchEventManager.js.map +1 -0
- package/lib/commonjs/web/utils.js +15 -0
- package/lib/commonjs/web/utils.js.map +1 -0
- package/lib/module/EnableExperimentalWebImplementation.js +5 -0
- package/lib/module/EnableExperimentalWebImplementation.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.js +1 -1
- package/lib/module/RNGestureHandlerModule.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.macos.js +19 -10
- package/lib/module/RNGestureHandlerModule.macos.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.web.js +22 -11
- package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
- package/lib/module/components/GestureComponents.web.js +1 -1
- package/lib/module/components/GestureComponents.web.js.map +1 -1
- package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js +1 -5
- package/lib/module/fabric/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js +1 -4
- package/lib/module/fabric/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/module/handlers/gestures/eventReceiver.js +14 -20
- package/lib/module/handlers/gestures/eventReceiver.js.map +1 -1
- package/lib/module/handlers/gestures/gestureStateManager.web.js +21 -0
- package/lib/module/handlers/gestures/gestureStateManager.web.js.map +1 -0
- package/lib/module/web/detectors/RotationGestureDetector.js +13 -17
- package/lib/module/web/detectors/RotationGestureDetector.js.map +1 -1
- package/lib/module/web/detectors/ScaleGestureDetector.js +3 -14
- package/lib/module/web/detectors/ScaleGestureDetector.js.map +1 -1
- package/lib/module/web/handlers/FlingGestureHandler.js +37 -12
- package/lib/module/web/handlers/FlingGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/GestureHandler.js +276 -79
- package/lib/module/web/handlers/GestureHandler.js.map +1 -1
- package/lib/module/web/handlers/LongPressGestureHandler.js +23 -18
- package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/ManualGestureHandler.js +39 -0
- package/lib/module/web/handlers/ManualGestureHandler.js.map +1 -0
- package/lib/module/web/handlers/NativeViewGestureHandler.js +80 -22
- package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PanGestureHandler.js +57 -41
- package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/PinchGestureHandler.js +43 -33
- package/lib/module/web/handlers/PinchGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/RotationGestureHandler.js +45 -38
- package/lib/module/web/handlers/RotationGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/TapGestureHandler.js +52 -50
- package/lib/module/web/handlers/TapGestureHandler.js.map +1 -1
- package/lib/module/web/interfaces.js +19 -0
- package/lib/module/web/interfaces.js.map +1 -1
- package/lib/module/web/tools/EventManager.js +39 -95
- package/lib/module/web/tools/EventManager.js.map +1 -1
- package/lib/module/web/tools/GestureHandlerOrchestrator.js +107 -30
- package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
- package/lib/module/web/tools/InteractionManager.js +24 -10
- package/lib/module/web/tools/InteractionManager.js.map +1 -1
- package/lib/module/web/tools/NodeManager.js.map +1 -1
- package/lib/module/web/tools/PointerEventManager.js +116 -0
- package/lib/module/web/tools/PointerEventManager.js.map +1 -0
- package/lib/module/web/tools/PointerTracker.js +97 -7
- package/lib/module/web/tools/PointerTracker.js.map +1 -1
- package/lib/module/web/tools/TouchEventManager.js +124 -0
- package/lib/module/web/tools/TouchEventManager.js.map +1 -0
- package/lib/module/web/utils.js +8 -0
- package/lib/module/web/utils.js.map +1 -0
- package/lib/typescript/RNGestureHandlerModule.macos.d.ts +5 -2
- package/lib/typescript/RNGestureHandlerModule.web.d.ts +5 -2
- package/lib/typescript/components/touchables/TouchableNativeFeedback.android.d.ts +1 -1
- package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +3 -3
- package/lib/typescript/fabric/RNGestureHandlerRootViewNativeComponent.d.ts +3 -2
- package/lib/typescript/handlers/gestures/gestureStateManager.web.d.ts +4 -0
- package/lib/typescript/web/detectors/RotationGestureDetector.d.ts +7 -7
- package/lib/typescript/web/detectors/ScaleGestureDetector.d.ts +6 -7
- package/lib/typescript/web/handlers/FlingGestureHandler.d.ts +12 -10
- package/lib/typescript/web/handlers/GestureHandler.d.ts +41 -32
- package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts +6 -9
- package/lib/typescript/web/handlers/ManualGestureHandler.d.ts +11 -0
- package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +15 -6
- package/lib/typescript/web/handlers/PanGestureHandler.d.ts +15 -23
- package/lib/typescript/web/handlers/PinchGestureHandler.d.ts +11 -12
- package/lib/typescript/web/handlers/RotationGestureHandler.d.ts +12 -12
- package/lib/typescript/web/handlers/TapGestureHandler.d.ts +11 -14
- package/lib/typescript/web/interfaces.d.ts +50 -10
- package/lib/typescript/web/tools/EventManager.d.ts +28 -26
- package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts +4 -2
- package/lib/typescript/web/tools/InteractionManager.d.ts +3 -0
- package/lib/typescript/web/tools/NodeManager.d.ts +3 -3
- package/lib/typescript/web/tools/PointerEventManager.d.ts +6 -0
- package/lib/typescript/web/tools/PointerTracker.d.ts +29 -5
- package/lib/typescript/web/tools/TouchEventManager.d.ts +6 -0
- package/lib/typescript/web/utils.d.ts +4 -0
- package/package.json +2 -2
- package/src/EnableExperimentalWebImplementation.ts +9 -0
- package/src/RNGestureHandlerModule.macos.ts +25 -10
- package/src/RNGestureHandlerModule.ts +4 -1
- package/src/RNGestureHandlerModule.web.ts +20 -7
- package/src/components/GestureComponents.web.tsx +1 -1
- package/src/fabric/RNGestureHandlerButtonNativeComponent.ts +2 -12
- package/src/fabric/RNGestureHandlerRootViewNativeComponent.ts +2 -8
- package/src/handlers/gestures/GestureDetector.tsx +0 -1
- package/src/handlers/gestures/eventReceiver.ts +23 -24
- package/src/handlers/gestures/gestureStateManager.web.ts +24 -0
- package/src/web/detectors/RotationGestureDetector.ts +20 -52
- package/src/web/detectors/ScaleGestureDetector.ts +9 -45
- package/src/web/handlers/FlingGestureHandler.ts +45 -22
- package/src/web/handlers/GestureHandler.ts +306 -97
- package/src/web/handlers/LongPressGestureHandler.ts +30 -24
- package/src/web/handlers/ManualGestureHandler.ts +39 -0
- package/src/web/handlers/NativeViewGestureHandler.ts +81 -24
- package/src/web/handlers/PanGestureHandler.ts +68 -53
- package/src/web/handlers/PinchGestureHandler.ts +47 -44
- package/src/web/handlers/RotationGestureHandler.ts +52 -51
- package/src/web/handlers/TapGestureHandler.ts +74 -56
- package/src/web/interfaces.ts +57 -10
- package/src/web/tools/EventManager.ts +58 -148
- package/src/web/tools/GestureHandlerOrchestrator.ts +115 -47
- package/src/web/tools/InteractionManager.ts +25 -9
- package/src/web/tools/NodeManager.ts +6 -6
- package/src/web/tools/PointerEventManager.ts +134 -0
- package/src/web/tools/PointerTracker.ts +120 -10
- package/src/web/tools/TouchEventManager.ts +167 -0
- package/src/web/utils.ts +8 -0
|
@@ -2,19 +2,26 @@ import GestureHandler from '../handlers/GestureHandler';
|
|
|
2
2
|
import { Config, Handler } from '../interfaces';
|
|
3
3
|
|
|
4
4
|
export default class InteractionManager {
|
|
5
|
+
private static instance: InteractionManager;
|
|
5
6
|
private readonly waitForRelations: Map<number, number[]> = new Map();
|
|
6
7
|
private readonly simultaneousRelations: Map<number, number[]> = new Map();
|
|
7
8
|
|
|
9
|
+
// Private becaues of singleton
|
|
10
|
+
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
|
|
11
|
+
private constructor() {}
|
|
12
|
+
|
|
8
13
|
public configureInteractions(handler: GestureHandler, config: Config) {
|
|
9
14
|
this.dropRelationsForHandlerWithTag(handler.getTag());
|
|
10
15
|
|
|
11
16
|
if (config.waitFor) {
|
|
12
17
|
const waitFor: number[] = [];
|
|
13
|
-
config.waitFor.forEach((
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
config.waitFor.forEach((otherHandler: Handler): void => {
|
|
19
|
+
// New API reference
|
|
20
|
+
if (typeof otherHandler === 'number') {
|
|
21
|
+
waitFor.push(otherHandler);
|
|
16
22
|
} else {
|
|
17
|
-
|
|
23
|
+
// Old API reference
|
|
24
|
+
waitFor.push(otherHandler.handlerTag);
|
|
18
25
|
}
|
|
19
26
|
});
|
|
20
27
|
|
|
@@ -23,17 +30,16 @@ export default class InteractionManager {
|
|
|
23
30
|
|
|
24
31
|
if (config.simultaneousHandlers) {
|
|
25
32
|
const simultaneousHandlers: number[] = [];
|
|
26
|
-
config.simultaneousHandlers.forEach((
|
|
27
|
-
if (typeof
|
|
28
|
-
simultaneousHandlers.push(
|
|
33
|
+
config.simultaneousHandlers.forEach((otherHandler: Handler): void => {
|
|
34
|
+
if (typeof otherHandler === 'number') {
|
|
35
|
+
simultaneousHandlers.push(otherHandler);
|
|
29
36
|
} else {
|
|
30
|
-
simultaneousHandlers.push(
|
|
37
|
+
simultaneousHandlers.push(otherHandler.handlerTag);
|
|
31
38
|
}
|
|
32
39
|
});
|
|
33
40
|
|
|
34
41
|
this.simultaneousRelations.set(handler.getTag(), simultaneousHandlers);
|
|
35
42
|
}
|
|
36
|
-
handler.setInteractionManager(this);
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
public shouldWaitForHandlerFailure(
|
|
@@ -86,6 +92,7 @@ export default class InteractionManager {
|
|
|
86
92
|
_handler: GestureHandler,
|
|
87
93
|
_otherHandler: GestureHandler
|
|
88
94
|
): boolean {
|
|
95
|
+
//TODO: Implement logic
|
|
89
96
|
return false;
|
|
90
97
|
}
|
|
91
98
|
|
|
@@ -93,6 +100,7 @@ export default class InteractionManager {
|
|
|
93
100
|
_handler: GestureHandler,
|
|
94
101
|
_otherHandler: GestureHandler
|
|
95
102
|
): boolean {
|
|
103
|
+
//TODO: Implement logic
|
|
96
104
|
return false;
|
|
97
105
|
}
|
|
98
106
|
|
|
@@ -105,4 +113,12 @@ export default class InteractionManager {
|
|
|
105
113
|
this.waitForRelations.clear();
|
|
106
114
|
this.simultaneousRelations.clear();
|
|
107
115
|
}
|
|
116
|
+
|
|
117
|
+
public static getInstance(): InteractionManager {
|
|
118
|
+
if (!this.instance) {
|
|
119
|
+
this.instance = new InteractionManager();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return this.instance;
|
|
123
|
+
}
|
|
108
124
|
}
|
|
@@ -2,13 +2,13 @@ import { ValueOf } from '../../typeUtils';
|
|
|
2
2
|
import { Gestures } from '../../RNGestureHandlerModule.web';
|
|
3
3
|
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
5
|
-
export default class NodeManager {
|
|
5
|
+
export default abstract class NodeManager {
|
|
6
6
|
private static gestures: Record<
|
|
7
7
|
number,
|
|
8
8
|
InstanceType<ValueOf<typeof Gestures>>
|
|
9
9
|
> = {};
|
|
10
10
|
|
|
11
|
-
static getHandler(tag: number) {
|
|
11
|
+
public static getHandler(tag: number) {
|
|
12
12
|
if (tag in this.gestures) {
|
|
13
13
|
return this.gestures[tag];
|
|
14
14
|
}
|
|
@@ -16,10 +16,10 @@ export default class NodeManager {
|
|
|
16
16
|
throw new Error(`No handler for tag ${tag}`);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
static createGestureHandler(
|
|
19
|
+
public static createGestureHandler(
|
|
20
20
|
handlerTag: number,
|
|
21
21
|
handler: InstanceType<ValueOf<typeof Gestures>>
|
|
22
|
-
) {
|
|
22
|
+
): void {
|
|
23
23
|
if (handlerTag in this.gestures) {
|
|
24
24
|
throw new Error(`Handler with tag ${handlerTag} already exists`);
|
|
25
25
|
}
|
|
@@ -28,7 +28,7 @@ export default class NodeManager {
|
|
|
28
28
|
this.gestures[handlerTag].setTag(handlerTag);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
static dropGestureHandler(handlerTag: number) {
|
|
31
|
+
public static dropGestureHandler(handlerTag: number): void {
|
|
32
32
|
if (!(handlerTag in this.gestures)) {
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
@@ -37,7 +37,7 @@ export default class NodeManager {
|
|
|
37
37
|
delete this.gestures[handlerTag];
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
static getNodes() {
|
|
40
|
+
public static getNodes() {
|
|
41
41
|
return { ...this.gestures };
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AdaptedEvent,
|
|
3
|
+
EventTypes,
|
|
4
|
+
MouseButtons,
|
|
5
|
+
PointerType,
|
|
6
|
+
} from '../interfaces';
|
|
7
|
+
import EventManager from './EventManager';
|
|
8
|
+
import { isPointerInBounds } from '../utils';
|
|
9
|
+
|
|
10
|
+
export default class PointerEventManager extends EventManager {
|
|
11
|
+
public setListeners(): void {
|
|
12
|
+
this.view.addEventListener('pointerdown', (event: PointerEvent): void => {
|
|
13
|
+
if (event.pointerType === PointerType.TOUCH) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (
|
|
17
|
+
!isPointerInBounds(this.view, { x: event.clientX, y: event.clientY })
|
|
18
|
+
) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.DOWN);
|
|
23
|
+
const target = event.target as HTMLElement;
|
|
24
|
+
|
|
25
|
+
target.setPointerCapture(adaptedEvent.pointerId);
|
|
26
|
+
this.markAsInBounds(adaptedEvent.pointerId);
|
|
27
|
+
|
|
28
|
+
if (++this.activePointersCounter > 1) {
|
|
29
|
+
adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
|
|
30
|
+
this.onPointerAdd(adaptedEvent);
|
|
31
|
+
} else {
|
|
32
|
+
this.onPointerDown(adaptedEvent);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
this.view.addEventListener('pointerup', (event: PointerEvent): void => {
|
|
37
|
+
if (event.pointerType === PointerType.TOUCH) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// When we call reset on gesture handlers, it also resets their event managers
|
|
42
|
+
// In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
|
|
43
|
+
// This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
|
|
44
|
+
// Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
|
|
45
|
+
if (this.activePointersCounter === 0) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.UP);
|
|
50
|
+
const target = event.target as HTMLElement;
|
|
51
|
+
|
|
52
|
+
target.releasePointerCapture(adaptedEvent.pointerId);
|
|
53
|
+
this.markAsOutOfBounds(adaptedEvent.pointerId);
|
|
54
|
+
|
|
55
|
+
if (--this.activePointersCounter > 0) {
|
|
56
|
+
adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
|
|
57
|
+
this.onPointerRemove(adaptedEvent);
|
|
58
|
+
} else {
|
|
59
|
+
this.onPointerUp(adaptedEvent);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.view.addEventListener('pointermove', (event: PointerEvent): void => {
|
|
64
|
+
if (event.pointerType === PointerType.TOUCH) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (
|
|
69
|
+
event.pointerType === PointerType.MOUSE &&
|
|
70
|
+
event.buttons !== MouseButtons.LEFT
|
|
71
|
+
) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.MOVE);
|
|
76
|
+
|
|
77
|
+
const inBounds: boolean = isPointerInBounds(this.view, {
|
|
78
|
+
x: adaptedEvent.x,
|
|
79
|
+
y: adaptedEvent.y,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const pointerIndex: number = this.pointersInBounds.indexOf(
|
|
83
|
+
adaptedEvent.pointerId
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (inBounds) {
|
|
87
|
+
if (pointerIndex < 0) {
|
|
88
|
+
adaptedEvent.eventType = EventTypes.ENTER;
|
|
89
|
+
this.onPointerEnter(adaptedEvent);
|
|
90
|
+
this.markAsInBounds(adaptedEvent.pointerId);
|
|
91
|
+
} else {
|
|
92
|
+
this.onPointerMove(adaptedEvent);
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
if (pointerIndex >= 0) {
|
|
96
|
+
adaptedEvent.eventType = EventTypes.OUT;
|
|
97
|
+
this.onPointerOut(adaptedEvent);
|
|
98
|
+
this.markAsOutOfBounds(adaptedEvent.pointerId);
|
|
99
|
+
} else {
|
|
100
|
+
this.onPointerOutOfBounds(adaptedEvent);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
this.view.addEventListener('pointercancel', (event: PointerEvent): void => {
|
|
106
|
+
if (event.pointerType === PointerType.TOUCH) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(
|
|
111
|
+
event,
|
|
112
|
+
EventTypes.CANCEL
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
this.onPointerCancel(adaptedEvent);
|
|
116
|
+
this.markAsOutOfBounds(adaptedEvent.pointerId);
|
|
117
|
+
this.activePointersCounter = 0;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
protected mapEvent(event: PointerEvent, eventType: EventTypes): AdaptedEvent {
|
|
122
|
+
return {
|
|
123
|
+
x: event.clientX,
|
|
124
|
+
y: event.clientY,
|
|
125
|
+
offsetX: event.offsetX,
|
|
126
|
+
offsetY: event.offsetY,
|
|
127
|
+
pointerId: event.pointerId,
|
|
128
|
+
eventType: eventType,
|
|
129
|
+
pointerType: event.pointerType as PointerType,
|
|
130
|
+
buttons: event.buttons,
|
|
131
|
+
time: event.timeStamp,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AdaptedEvent } from '../interfaces';
|
|
2
2
|
|
|
3
|
-
interface TrackerElement {
|
|
3
|
+
export interface TrackerElement {
|
|
4
4
|
lastX: number;
|
|
5
5
|
lastY: number;
|
|
6
6
|
|
|
@@ -10,7 +10,9 @@ interface TrackerElement {
|
|
|
10
10
|
velocityY: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
// Used to scale velocity so that it is similar to velocity in Android/iOS
|
|
13
14
|
const VELOCITY_FACTOR = 0.2;
|
|
15
|
+
const MAX_POINTERS = 20;
|
|
14
16
|
|
|
15
17
|
export default class PointerTracker {
|
|
16
18
|
private trackedPointers: Map<number, TrackerElement> = new Map<
|
|
@@ -18,11 +20,27 @@ export default class PointerTracker {
|
|
|
18
20
|
TrackerElement
|
|
19
21
|
>();
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
private touchEventsIds: Map<number, number> = new Map<number, number>();
|
|
24
|
+
|
|
25
|
+
private lastMovedPointerId: number;
|
|
26
|
+
|
|
27
|
+
private cachedAverages: { x: number; y: number } = { x: 0, y: 0 };
|
|
28
|
+
|
|
29
|
+
public constructor() {
|
|
30
|
+
this.lastMovedPointerId = NaN;
|
|
31
|
+
|
|
32
|
+
for (let i = 0; i < MAX_POINTERS; ++i) {
|
|
33
|
+
this.touchEventsIds.set(i, NaN);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public addToTracker(event: AdaptedEvent): void {
|
|
22
38
|
if (this.trackedPointers.has(event.pointerId)) {
|
|
23
39
|
return;
|
|
24
40
|
}
|
|
25
41
|
|
|
42
|
+
this.lastMovedPointerId = event.pointerId;
|
|
43
|
+
|
|
26
44
|
const newElement: TrackerElement = {
|
|
27
45
|
lastX: event.x,
|
|
28
46
|
lastY: event.y,
|
|
@@ -32,13 +50,20 @@ export default class PointerTracker {
|
|
|
32
50
|
};
|
|
33
51
|
|
|
34
52
|
this.trackedPointers.set(event.pointerId, newElement);
|
|
53
|
+
this.mapTouchEventId(event.pointerId);
|
|
54
|
+
|
|
55
|
+
this.cachedAverages = {
|
|
56
|
+
x: this.getLastAvgX(),
|
|
57
|
+
y: this.getLastAvgY(),
|
|
58
|
+
};
|
|
35
59
|
}
|
|
36
60
|
|
|
37
61
|
public removeFromTracker(pointerId: number): void {
|
|
38
62
|
this.trackedPointers.delete(pointerId);
|
|
63
|
+
this.removeMappedTouchId(pointerId);
|
|
39
64
|
}
|
|
40
65
|
|
|
41
|
-
public track(event:
|
|
66
|
+
public track(event: AdaptedEvent): void {
|
|
42
67
|
const element: TrackerElement = this.trackedPointers.get(
|
|
43
68
|
event.pointerId
|
|
44
69
|
) as TrackerElement;
|
|
@@ -47,6 +72,8 @@ export default class PointerTracker {
|
|
|
47
72
|
return;
|
|
48
73
|
}
|
|
49
74
|
|
|
75
|
+
this.lastMovedPointerId = event.pointerId;
|
|
76
|
+
|
|
50
77
|
const dx = event.x - element.lastX;
|
|
51
78
|
const dy = event.y - element.lastY;
|
|
52
79
|
const dt = event.time - element.timeStamp;
|
|
@@ -58,6 +85,41 @@ export default class PointerTracker {
|
|
|
58
85
|
element.lastY = event.y;
|
|
59
86
|
|
|
60
87
|
this.trackedPointers.set(event.pointerId, element);
|
|
88
|
+
|
|
89
|
+
const avgX: number = this.getLastAvgX();
|
|
90
|
+
const avgY: number = this.getLastAvgY();
|
|
91
|
+
|
|
92
|
+
this.cachedAverages = {
|
|
93
|
+
x: avgX,
|
|
94
|
+
y: avgY,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//Mapping TouchEvents ID
|
|
99
|
+
private mapTouchEventId(id: number): void {
|
|
100
|
+
for (const [mappedId, touchId] of this.touchEventsIds) {
|
|
101
|
+
if (isNaN(touchId)) {
|
|
102
|
+
this.touchEventsIds.set(mappedId, id);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private removeMappedTouchId(id: number): void {
|
|
109
|
+
const mappedId: number = this.getMappedTouchEventId(id);
|
|
110
|
+
if (!isNaN(mappedId)) {
|
|
111
|
+
this.touchEventsIds.set(mappedId, NaN);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
public getMappedTouchEventId(touchEventId: number): number {
|
|
116
|
+
for (const [key, value] of this.touchEventsIds.entries()) {
|
|
117
|
+
if (value === touchEventId) {
|
|
118
|
+
return key;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return NaN;
|
|
61
123
|
}
|
|
62
124
|
|
|
63
125
|
public getVelocityX(pointerId: number): number {
|
|
@@ -66,17 +128,60 @@ export default class PointerTracker {
|
|
|
66
128
|
public getVelocityY(pointerId: number): number {
|
|
67
129
|
return this.trackedPointers.get(pointerId)?.velocityY as number;
|
|
68
130
|
}
|
|
69
|
-
|
|
70
|
-
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Returns X coordinate of last moved pointer
|
|
134
|
+
*/
|
|
135
|
+
public getLastX(): number;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
* @param pointerId
|
|
140
|
+
* Returns X coordinate of given pointer
|
|
141
|
+
*/
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/unified-signatures
|
|
143
|
+
public getLastX(pointerId: number): number;
|
|
144
|
+
|
|
145
|
+
public getLastX(pointerId?: number): number {
|
|
146
|
+
if (pointerId) {
|
|
147
|
+
return this.trackedPointers.get(pointerId)?.lastX as number;
|
|
148
|
+
} else {
|
|
149
|
+
return this.trackedPointers.get(this.lastMovedPointerId)?.lastX as number;
|
|
150
|
+
}
|
|
71
151
|
}
|
|
72
|
-
|
|
73
|
-
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Returns Y coordinate of last moved pointer
|
|
155
|
+
*/
|
|
156
|
+
public getLastY(): number;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* @param pointerId
|
|
161
|
+
* Returns Y coordinate of given pointer
|
|
162
|
+
*/
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/unified-signatures
|
|
164
|
+
public getLastY(pointerId: number): number;
|
|
165
|
+
|
|
166
|
+
public getLastY(pointerId?: number): number {
|
|
167
|
+
if (pointerId) {
|
|
168
|
+
return this.trackedPointers.get(pointerId)?.lastY as number;
|
|
169
|
+
} else {
|
|
170
|
+
return this.trackedPointers.get(this.lastMovedPointerId)?.lastY as number;
|
|
171
|
+
}
|
|
74
172
|
}
|
|
173
|
+
|
|
174
|
+
// Some handlers use these methods to send average values in native event.
|
|
175
|
+
// This may happen when pointers have already been removed from tracker (i.e. pointerup event).
|
|
176
|
+
// In situation when NaN would be sent as a response, we return cached value.
|
|
177
|
+
// That prevents handlers from crashing
|
|
75
178
|
public getLastAvgX(): number {
|
|
76
|
-
|
|
179
|
+
const avgX: number = this.getSumX() / this.trackedPointers.size;
|
|
180
|
+
return isNaN(avgX) ? this.cachedAverages.x : avgX;
|
|
77
181
|
}
|
|
78
182
|
public getLastAvgY(): number {
|
|
79
|
-
|
|
183
|
+
const avgY: number = this.getSumY() / this.trackedPointers.size;
|
|
184
|
+
return isNaN(avgY) ? this.cachedAverages.y : avgY;
|
|
80
185
|
}
|
|
81
186
|
public getSumX(ignoredPointer?: number): number {
|
|
82
187
|
let sumX = 0;
|
|
@@ -119,6 +224,11 @@ export default class PointerTracker {
|
|
|
119
224
|
|
|
120
225
|
public resetTracker(): void {
|
|
121
226
|
this.trackedPointers.clear();
|
|
227
|
+
this.lastMovedPointerId = NaN;
|
|
228
|
+
|
|
229
|
+
for (let i = 0; i < MAX_POINTERS; ++i) {
|
|
230
|
+
this.touchEventsIds.set(i, NaN);
|
|
231
|
+
}
|
|
122
232
|
}
|
|
123
233
|
|
|
124
234
|
public static shareCommonPointers(
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AdaptedEvent,
|
|
3
|
+
EventTypes,
|
|
4
|
+
MouseButtons,
|
|
5
|
+
PointerType,
|
|
6
|
+
TouchEventType,
|
|
7
|
+
} from '../interfaces';
|
|
8
|
+
import EventManager from './EventManager';
|
|
9
|
+
import { isPointerInBounds } from '../utils';
|
|
10
|
+
|
|
11
|
+
export default class TouchEventManager extends EventManager {
|
|
12
|
+
public setListeners(): void {
|
|
13
|
+
this.view.addEventListener('touchstart', (event: TouchEvent) => {
|
|
14
|
+
for (let i = 0; i < event.changedTouches.length; ++i) {
|
|
15
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(
|
|
16
|
+
event,
|
|
17
|
+
EventTypes.DOWN,
|
|
18
|
+
i,
|
|
19
|
+
TouchEventType.DOWN
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// Here we skip stylus, because in case of anything different than touch we want to handle it by using PointerEvents
|
|
23
|
+
// If we leave stylus to send touch events, handlers will receive every action twice
|
|
24
|
+
if (
|
|
25
|
+
!isPointerInBounds(this.view, {
|
|
26
|
+
x: adaptedEvent.x,
|
|
27
|
+
y: adaptedEvent.y,
|
|
28
|
+
}) ||
|
|
29
|
+
//@ts-ignore touchType field does exist
|
|
30
|
+
event.changedTouches[i].touchType === 'stylus'
|
|
31
|
+
) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.markAsInBounds(adaptedEvent.pointerId);
|
|
36
|
+
|
|
37
|
+
if (++this.activePointersCounter > 1) {
|
|
38
|
+
adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
|
|
39
|
+
this.onPointerAdd(adaptedEvent);
|
|
40
|
+
} else {
|
|
41
|
+
this.onPointerDown(adaptedEvent);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.view.addEventListener('touchmove', (event: TouchEvent) => {
|
|
47
|
+
for (let i = 0; i < event.changedTouches.length; ++i) {
|
|
48
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(
|
|
49
|
+
event,
|
|
50
|
+
EventTypes.MOVE,
|
|
51
|
+
i,
|
|
52
|
+
TouchEventType.MOVE
|
|
53
|
+
);
|
|
54
|
+
//@ts-ignore touchType field does exist
|
|
55
|
+
if (event.changedTouches[i].touchType === 'stylus') {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const inBounds: boolean = isPointerInBounds(this.view, {
|
|
60
|
+
x: adaptedEvent.x,
|
|
61
|
+
y: adaptedEvent.y,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const pointerIndex: number = this.pointersInBounds.indexOf(
|
|
65
|
+
adaptedEvent.pointerId
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
if (inBounds) {
|
|
69
|
+
if (pointerIndex < 0) {
|
|
70
|
+
adaptedEvent.eventType = EventTypes.ENTER;
|
|
71
|
+
this.onPointerEnter(adaptedEvent);
|
|
72
|
+
this.markAsInBounds(adaptedEvent.pointerId);
|
|
73
|
+
} else {
|
|
74
|
+
this.onPointerMove(adaptedEvent);
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
if (pointerIndex >= 0) {
|
|
78
|
+
adaptedEvent.eventType = EventTypes.OUT;
|
|
79
|
+
this.onPointerOut(adaptedEvent);
|
|
80
|
+
this.markAsOutOfBounds(adaptedEvent.pointerId);
|
|
81
|
+
} else {
|
|
82
|
+
this.onPointerOutOfBounds(adaptedEvent);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
this.view.addEventListener('touchend', (event: TouchEvent) => {
|
|
89
|
+
for (let i = 0; i < event.changedTouches.length; ++i) {
|
|
90
|
+
// When we call reset on gesture handlers, it also resets their event managers
|
|
91
|
+
// In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
|
|
92
|
+
// This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
|
|
93
|
+
// Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
|
|
94
|
+
if (this.activePointersCounter === 0) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//@ts-ignore touchType field does exist
|
|
99
|
+
if (event.changedTouches[i].touchType === 'stylus') {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(
|
|
104
|
+
event,
|
|
105
|
+
EventTypes.UP,
|
|
106
|
+
i,
|
|
107
|
+
TouchEventType.UP
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
this.markAsOutOfBounds(adaptedEvent.pointerId);
|
|
111
|
+
|
|
112
|
+
if (--this.activePointersCounter > 0) {
|
|
113
|
+
adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
|
|
114
|
+
this.onPointerRemove(adaptedEvent);
|
|
115
|
+
} else {
|
|
116
|
+
this.onPointerUp(adaptedEvent);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
this.view.addEventListener('touchcancel', (event: TouchEvent) => {
|
|
122
|
+
for (let i = 0; i < event.changedTouches.length; ++i) {
|
|
123
|
+
const adaptedEvent: AdaptedEvent = this.mapEvent(
|
|
124
|
+
event,
|
|
125
|
+
EventTypes.CANCEL,
|
|
126
|
+
i,
|
|
127
|
+
TouchEventType.CANCELLED
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
//@ts-ignore touchType field does exist
|
|
131
|
+
if (event.changedTouches[i].touchType === 'stylus') {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.onPointerCancel(adaptedEvent);
|
|
136
|
+
this.markAsOutOfBounds(adaptedEvent.pointerId);
|
|
137
|
+
this.activePointersCounter = 0;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
protected mapEvent(
|
|
143
|
+
event: TouchEvent,
|
|
144
|
+
eventType: EventTypes,
|
|
145
|
+
index: number,
|
|
146
|
+
touchEventType: TouchEventType
|
|
147
|
+
): AdaptedEvent {
|
|
148
|
+
const rect = this.view.getBoundingClientRect();
|
|
149
|
+
const clientX = event.changedTouches[index].clientX;
|
|
150
|
+
const clientY = event.changedTouches[index].clientY;
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
x: clientX,
|
|
154
|
+
y: clientY,
|
|
155
|
+
offsetX: clientX - rect.left,
|
|
156
|
+
offsetY: clientY - rect.top,
|
|
157
|
+
pointerId: event.changedTouches[index].identifier,
|
|
158
|
+
eventType: eventType,
|
|
159
|
+
pointerType: PointerType.TOUCH,
|
|
160
|
+
buttons: MouseButtons.NONE,
|
|
161
|
+
time: event.timeStamp,
|
|
162
|
+
allTouches: event.touches,
|
|
163
|
+
changedTouches: event.changedTouches,
|
|
164
|
+
touchEventType: touchEventType,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
package/src/web/utils.ts
ADDED