@react-native-oh-tpl/react-native-gesture-handler 2.14.7 → 2.14.13

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.
Files changed (117) hide show
  1. package/DrawerLayout/index.ts +2 -2
  2. package/Swipeable/index.ts +2 -2
  3. package/harmony/gesture_handler/BuildProfile.ets +17 -0
  4. package/harmony/gesture_handler/build-profile.json5 +19 -0
  5. package/harmony/gesture_handler/hvigorfile.ts +2 -0
  6. package/harmony/gesture_handler/index.ets +3 -0
  7. package/harmony/gesture_handler/oh-package-lock.json5 +18 -0
  8. package/harmony/gesture_handler/oh-package.json5 +12 -0
  9. package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -0
  10. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +149 -0
  11. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +21 -0
  12. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonComponentDescriptor.h +36 -0
  13. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonJSIBinder.h +32 -0
  14. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.cpp +22 -0
  15. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.h +15 -0
  16. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentDescriptor.h +36 -0
  17. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewJSIBinder.h +25 -0
  18. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +27 -0
  19. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +242 -0
  20. package/harmony/gesture_handler/src/main/ets/core/CircularBuffer.ts +42 -0
  21. package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +690 -0
  22. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +335 -0
  23. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +63 -0
  24. package/harmony/gesture_handler/src/main/ets/core/IncomingEvent.ts +78 -0
  25. package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
  26. package/harmony/gesture_handler/src/main/ets/core/LeastSquareSolver.ts +182 -0
  27. package/harmony/gesture_handler/src/main/ets/core/OutgoingEvent.ts +34 -0
  28. package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
  29. package/harmony/gesture_handler/src/main/ets/core/PointerTracker.ts +239 -0
  30. package/harmony/gesture_handler/src/main/ets/core/RNGHError.ts +5 -0
  31. package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +12 -0
  32. package/harmony/gesture_handler/src/main/ets/core/State.ts +47 -0
  33. package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
  34. package/harmony/gesture_handler/src/main/ets/core/VelocityTracker.ts +106 -0
  35. package/harmony/gesture_handler/src/main/ets/core/View.ts +21 -0
  36. package/harmony/gesture_handler/src/main/ets/core/ViewFinder.ts +11 -0
  37. package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +8 -0
  38. package/harmony/gesture_handler/src/main/ets/core/index.ts +15 -0
  39. package/harmony/gesture_handler/src/main/ets/detectors/ScaleGestureDetector.ts +169 -0
  40. package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +211 -0
  41. package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +64 -0
  42. package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +127 -0
  43. package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +42 -0
  44. package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +115 -0
  45. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +342 -0
  46. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +159 -0
  47. package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +164 -0
  48. package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +206 -0
  49. package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts +167 -0
  50. package/harmony/gesture_handler/src/main/ets/gesture-handlers/index.ts +1 -0
  51. package/harmony/gesture_handler/src/main/ets/namespace/RNGestureHandlerModule.ts +24 -0
  52. package/harmony/gesture_handler/src/main/ets/namespace/components/RNGestureHandlerButton.ts +139 -0
  53. package/harmony/gesture_handler/src/main/ets/namespace/components/RNGestureHandlerRootView.ts +101 -0
  54. package/harmony/gesture_handler/src/main/ets/namespace/components/ts.ts +2 -0
  55. package/harmony/gesture_handler/src/main/ets/namespace/ts.ts +2 -0
  56. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerArkUIAdapter.ts +240 -0
  57. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +22 -0
  58. package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +49 -0
  59. package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +71 -0
  60. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerArkTS.ts +98 -0
  61. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +110 -0
  62. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerButton.ets +38 -0
  63. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +233 -0
  64. package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerRootView.ets +53 -0
  65. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +24 -0
  66. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +32 -0
  67. package/harmony/gesture_handler/src/main/ets/rnoh/View.ts +134 -0
  68. package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +97 -0
  69. package/harmony/gesture_handler/src/main/ets/rnoh/types.ts +25 -0
  70. package/harmony/gesture_handler/src/main/module.json5 +9 -0
  71. package/harmony/gesture_handler/src/main/resources/base/element/color.json +8 -0
  72. package/harmony/gesture_handler/src/main/resources/base/element/string.json +16 -0
  73. package/harmony/gesture_handler/src/main/resources/base/media/icon.png +0 -0
  74. package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -0
  75. package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +16 -0
  76. package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +16 -0
  77. package/harmony/gesture_handler/ts.ts +2 -0
  78. package/harmony/gesture_handler.har +0 -0
  79. package/lib/commonjs/RNGestureHandlerModule.js +3 -2
  80. package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
  81. package/lib/commonjs/components/GestureHandlerRootView.js +3 -3
  82. package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
  83. package/lib/commonjs/handlers/createHandler.js +18 -15
  84. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  85. package/lib/commonjs/index.js +36 -8
  86. package/lib/commonjs/index.js.map +1 -1
  87. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js +2 -1
  88. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  89. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js +3 -2
  90. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  91. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js +3 -2
  92. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  93. package/lib/module/RNGestureHandlerModule.js.map +1 -1
  94. package/lib/module/components/GestureHandlerRootView.js.map +1 -1
  95. package/lib/module/handlers/createHandler.js +15 -12
  96. package/lib/module/handlers/createHandler.js.map +1 -1
  97. package/lib/module/index.js +5 -7
  98. package/lib/module/index.js.map +1 -1
  99. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  100. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  101. package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
  102. package/lib/typescript/RNGestureHandlerModule.d.ts +2 -2
  103. package/lib/typescript/components/GestureHandlerRootView.d.ts +6 -6
  104. package/lib/typescript/handlers/createHandler.d.ts +11 -11
  105. package/lib/typescript/index.d.ts +47 -42
  106. package/lib/typescript/index.d.ts.map +1 -1
  107. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +14 -14
  108. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +14 -14
  109. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +6 -6
  110. package/package.json +73 -72
  111. package/src/RNGestureHandlerModule.ts +4 -4
  112. package/src/components/GestureHandlerRootView.tsx +23 -23
  113. package/src/handlers/createHandler.tsx +534 -534
  114. package/src/index.ts +172 -172
  115. package/src/specs/NativeRNGestureHandlerModule.ts +26 -26
  116. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +18 -18
  117. package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +6 -6
@@ -0,0 +1,159 @@
1
+ import { GestureHandler, DEFAULT_TOUCH_SLOP, IncomingEvent, GestureConfig, State, GestureHandlerDependencies } from "../core"
2
+ import ScaleGestureDetector, { ScaleGestureListener } from "../detectors/ScaleGestureDetector";
3
+
4
+
5
+
6
+ export class PinchGestureHandler extends GestureHandler {
7
+ private scale = 1;
8
+ private velocity = 0;
9
+
10
+ private startingSpan = 0;
11
+ private spanSlop = DEFAULT_TOUCH_SLOP;
12
+
13
+ private scaleDetectorListener: ScaleGestureListener = {
14
+ onScaleBegin: (detector: ScaleGestureDetector): boolean => {
15
+ this.startingSpan = detector.getCurrentSpan();
16
+ return true;
17
+ },
18
+ onScale: (detector: ScaleGestureDetector): boolean => {
19
+ const prevScaleFactor: number = this.scale;
20
+ this.scale *= detector.getScaleFactor(
21
+ this.tracker.getTrackedPointersCount()
22
+ );
23
+
24
+ const delta = detector.getTimeDelta();
25
+ if (delta > 0) {
26
+ this.velocity = (this.scale - prevScaleFactor) / delta;
27
+ }
28
+
29
+ if (
30
+ Math.abs(this.startingSpan - detector.getCurrentSpan()) >=
31
+ this.spanSlop &&
32
+ this.currentState === State.BEGAN
33
+ ) {
34
+ this.activate();
35
+ }
36
+ return true;
37
+ },
38
+ onScaleEnd: (
39
+ _detector: ScaleGestureDetector
40
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
41
+ ): void => {},
42
+ };
43
+
44
+ private scaleGestureDetector: ScaleGestureDetector = new ScaleGestureDetector(
45
+ this.scaleDetectorListener
46
+ );
47
+
48
+
49
+ public constructor(deps: GestureHandlerDependencies) {
50
+ super({ ...deps, logger: deps.logger.cloneWithPrefix("PinchGestureHandler") })
51
+ this.setShouldCancelWhenOutside(false);
52
+ }
53
+
54
+ public getDefaultConfig() {
55
+ return {}
56
+ }
57
+
58
+ public updateGestureConfig({ enabled = true, ...props }: GestureConfig): void {
59
+ super.updateGestureConfig({ enabled: enabled, ...props });
60
+ }
61
+
62
+ protected transformNativeEvent() {
63
+ return {
64
+ focalX: this.scaleGestureDetector.getFocusX(),
65
+ focalY: this.scaleGestureDetector.getFocusY(),
66
+ velocity: this.velocity,
67
+ scale: this.scale,
68
+ };
69
+ }
70
+
71
+ public onPointerDown(event: IncomingEvent): void {
72
+ this.tracker.addToTracker(event);
73
+ super.onPointerDown(event);
74
+ }
75
+
76
+ public onAdditionalPointerAdd(event: IncomingEvent): void {
77
+ this.tracker.addToTracker(event);
78
+ super.onAdditionalPointerAdd(event);
79
+ this.tryBegin();
80
+ this.scaleGestureDetector.onTouchEvent(event, this.tracker);
81
+ }
82
+
83
+ public onPointerUp(event: IncomingEvent): void {
84
+ super.onPointerUp(event);
85
+ this.tracker.removeFromTracker(event.pointerId);
86
+ if (this.currentState !== State.ACTIVE) {
87
+ return;
88
+ }
89
+ this.scaleGestureDetector.onTouchEvent(event, this.tracker);
90
+
91
+ if (this.currentState === State.ACTIVE) {
92
+ this.end();
93
+ } else {
94
+ this.fail();
95
+ }
96
+ }
97
+
98
+ public onAdditionalPointerRemove(event: IncomingEvent): void {
99
+ super.onAdditionalPointerRemove(event);
100
+ this.scaleGestureDetector.onTouchEvent(event, this.tracker);
101
+ this.tracker.removeFromTracker(event.pointerId);
102
+
103
+ if (
104
+ this.currentState === State.ACTIVE &&
105
+ this.tracker.getTrackedPointersCount() < 2
106
+ ) {
107
+ this.end();
108
+ }
109
+ }
110
+
111
+ public onPointerMove(event: IncomingEvent): void {
112
+ if (this.tracker.getTrackedPointersCount() < 2) {
113
+ return;
114
+ }
115
+ this.tracker.track(event);
116
+
117
+ this.scaleGestureDetector.onTouchEvent(event, this.tracker);
118
+ super.onPointerMove(event);
119
+ }
120
+
121
+ public onPointerOutOfBounds(event: IncomingEvent): void {
122
+ if (this.tracker.getTrackedPointersCount() < 2) {
123
+ return;
124
+ }
125
+ this.tracker.track(event);
126
+
127
+ this.scaleGestureDetector.onTouchEvent(event, this.tracker);
128
+ super.onPointerOutOfBounds(event);
129
+ }
130
+
131
+ private tryBegin(): void {
132
+ if (this.currentState !== State.UNDETERMINED) {
133
+ return;
134
+ }
135
+
136
+ this.resetProgress();
137
+ this.begin();
138
+ }
139
+
140
+ public activate(force?: boolean): void {
141
+ if (this.currentState !== State.ACTIVE) {
142
+ this.resetProgress();
143
+ }
144
+
145
+ super.activate();
146
+ }
147
+
148
+ protected onReset(): void {
149
+ this.resetProgress();
150
+ }
151
+
152
+ protected resetProgress(): void {
153
+ if (this.currentState === State.ACTIVE) {
154
+ return;
155
+ }
156
+ this.velocity = 0;
157
+ this.scale = 1;
158
+ }
159
+ }
@@ -0,0 +1,164 @@
1
+ import { GestureHandler, State, IncomingEvent, GestureConfig, GestureHandlerDependencies } from '../core';
2
+ import RotationGestureDetector, { RotationGestureListener, } from './detectors/RotationGestureDetector';
3
+
4
+ const ROTATION_RECOGNITION_THRESHOLD = Math.PI / 36;
5
+
6
+ export class RotationGestureHandler extends GestureHandler {
7
+ private rotation = 0;
8
+ private velocity = 0;
9
+
10
+ private cachedAnchorX = 0;
11
+ private cachedAnchorY = 0;
12
+ private unlockScrolls: (() => void) | undefined
13
+
14
+ constructor(deps: GestureHandlerDependencies) {
15
+ super({ ...deps, logger: deps.logger.cloneWithPrefix("RotationGestureHandler") })
16
+ }
17
+
18
+ private rotationGestureListener: RotationGestureListener = {
19
+ onRotationBegin: (_detector: RotationGestureDetector): boolean => true,
20
+ onRotation: (detector: RotationGestureDetector): boolean => {
21
+ const previousRotation: number = this.rotation;
22
+ this.rotation += detector.getRotation();
23
+
24
+ const delta = detector.getTimeDelta();
25
+
26
+ if (delta > 0) {
27
+ this.velocity = (this.rotation - previousRotation) / delta;
28
+ }
29
+
30
+ if (
31
+ Math.abs(this.rotation) >= ROTATION_RECOGNITION_THRESHOLD &&
32
+ this.currentState === State.BEGAN
33
+ ) {
34
+ this.activate();
35
+ }
36
+
37
+ return true;
38
+ },
39
+ onRotationEnd: (_detector: RotationGestureDetector): void => {
40
+ this.end();
41
+ },
42
+ };
43
+
44
+ private rotationGestureDetector: RotationGestureDetector =
45
+ new RotationGestureDetector(this.rotationGestureListener);
46
+
47
+ getDefaultConfig(): GestureConfig {
48
+ return { shouldCancelWhenOutside: false }
49
+ }
50
+
51
+ protected transformNativeEvent() {
52
+ return {
53
+ rotation: this.rotation ? this.rotation : 0,
54
+ anchorX: this.getAnchorX(),
55
+ anchorY: this.getAnchorY(),
56
+ velocity: this.velocity ? this.velocity : 0,
57
+ };
58
+ }
59
+
60
+ public getAnchorX(): number {
61
+ const anchorX = this.rotationGestureDetector.getAnchorX();
62
+
63
+ return anchorX ? anchorX : this.cachedAnchorX;
64
+ }
65
+
66
+ public getAnchorY(): number {
67
+ const anchorY = this.rotationGestureDetector.getAnchorY();
68
+
69
+ return anchorY ? anchorY : this.cachedAnchorY;
70
+ }
71
+
72
+ public onPointerDown(event: IncomingEvent): void {
73
+ this.tracker.addToTracker(event);
74
+ super.onPointerDown(event);
75
+ }
76
+
77
+ public onAdditionalPointerAdd(event: IncomingEvent): void {
78
+ this.tracker.addToTracker(event);
79
+ super.onAdditionalPointerAdd(event);
80
+ this.tryBegin();
81
+ this.rotationGestureDetector.onTouchEvent(event, this.tracker);
82
+ }
83
+
84
+ public onPointerMove(event: IncomingEvent): void {
85
+ if (this.tracker.getTrackedPointersCount() < 2) {
86
+ return;
87
+ }
88
+ if (this.getAnchorX()) {
89
+ this.cachedAnchorX = this.getAnchorX();
90
+ }
91
+ if (this.getAnchorY()) {
92
+ this.cachedAnchorY = this.getAnchorY();
93
+ }
94
+ this.tracker.track(event);
95
+ this.rotationGestureDetector.onTouchEvent(event, this.tracker);
96
+ super.onPointerMove(event);
97
+ }
98
+
99
+ public onPointerOutOfBounds(event: IncomingEvent): void {
100
+ if (this.tracker.getTrackedPointersCount() < 2) {
101
+ return;
102
+ }
103
+ if (this.getAnchorX()) {
104
+ this.cachedAnchorX = this.getAnchorX();
105
+ }
106
+ if (this.getAnchorY()) {
107
+ this.cachedAnchorY = this.getAnchorY();
108
+ }
109
+ this.tracker.track(event);
110
+ this.rotationGestureDetector.onTouchEvent(event, this.tracker);
111
+ super.onPointerOutOfBounds(event);
112
+ }
113
+
114
+ public onPointerUp(event: IncomingEvent): void {
115
+ super.onPointerUp(event);
116
+ this.tracker.removeFromTracker(event.pointerId);
117
+ this.rotationGestureDetector.onTouchEvent(event, this.tracker);
118
+ if (this.currentState !== State.ACTIVE) {
119
+ return;
120
+ }
121
+ if (this.currentState === State.ACTIVE) {
122
+ this.end();
123
+ } else {
124
+ this.fail();
125
+ }
126
+ }
127
+
128
+ public onAdditionalPointerRemove(event: IncomingEvent): void {
129
+ super.onAdditionalPointerRemove(event);
130
+ this.rotationGestureDetector.onTouchEvent(event, this.tracker);
131
+ this.tracker.removeFromTracker(event.pointerId);
132
+ }
133
+
134
+ protected tryBegin(): void {
135
+ if (this.currentState !== State.UNDETERMINED) {
136
+ return;
137
+ }
138
+
139
+ this.begin();
140
+ }
141
+
142
+ public activate(): void {
143
+ super.activate();
144
+ }
145
+
146
+ protected onReset(): void {
147
+ if (this.currentState === State.ACTIVE) {
148
+ return;
149
+ }
150
+
151
+ this.rotation = 0;
152
+ this.velocity = 0;
153
+ this.rotationGestureDetector.reset();
154
+ }
155
+
156
+ protected onStateChange(newState: State, oldState: State) {
157
+ super.onStateChange(newState, oldState)
158
+ if (newState === State.BEGAN) {
159
+ this.unlockScrolls = this.scrollLocker.lockScrollContainingViewTag(this.view?.getTag())
160
+ } else if (newState !== State.ACTIVE) {
161
+ this.unlockScrolls?.()
162
+ }
163
+ }
164
+ }
@@ -0,0 +1,206 @@
1
+ import { GestureHandler, GestureHandlerDependencies, IncomingEvent, EventType, State, getStateName } from "../core"
2
+
3
+ const DEFAULT_MAX_DURATION_MS = 500;
4
+ const DEFAULT_NUMBER_OF_TAPS = 1;
5
+ const DEFAULT_MAX_DELAY_MS = 500;
6
+
7
+ export class TapGestureHandler extends GestureHandler {
8
+ private startX = 0;
9
+ private startY = 0;
10
+ private offsetX = 0;
11
+ private offsetY = 0;
12
+ private lastX = 0;
13
+ private lastY = 0;
14
+ private maxNumberOfPointersSoFar = 0;
15
+ private numberOfTapsSoFar: number = 0;
16
+ private waitTimeout: number | undefined;
17
+ private delayTimeout: number | undefined;
18
+
19
+ constructor(deps: GestureHandlerDependencies) {
20
+ super({...deps, logger: deps.logger.cloneWithPrefix(`TapGestureHandler${deps.handlerTag}`)})
21
+ }
22
+
23
+ onPointerDown(event) {
24
+ this.tracker.addToTracker(event);
25
+ super.onPointerDown(event);
26
+ this.trySettingPosition(event);
27
+ this.lastX = event.x;
28
+ this.lastY = event.y;
29
+ this.updateState(event);
30
+ }
31
+
32
+ onAdditionalPointerAdd(event: IncomingEvent): void {
33
+ super.onAdditionalPointerAdd(event);
34
+ this.tracker.addToTracker(event);
35
+ this.trySettingPosition(event);
36
+
37
+ this.offsetX += this.lastX - this.startX;
38
+ this.offsetY += this.lastY - this.startY;
39
+
40
+ this.lastX = this.tracker.getLastAvgX();
41
+ this.lastY = this.tracker.getLastAvgY();
42
+
43
+ this.startX = this.tracker.getLastAvgX();
44
+ this.startY = this.tracker.getLastAvgY();
45
+
46
+ this.updateState(event);
47
+ }
48
+
49
+ onPointerUp(event: IncomingEvent): void {
50
+ super.onPointerUp(event);
51
+ this.lastX = this.tracker.getLastAvgX();
52
+ this.lastY = this.tracker.getLastAvgY();
53
+
54
+ this.tracker.removeFromTracker(event.pointerId);
55
+
56
+ this.updateState(event);
57
+ }
58
+
59
+ onAdditionalPointerRemove(event: IncomingEvent): void {
60
+ super.onAdditionalPointerRemove(event);
61
+ this.tracker.removeFromTracker(event.pointerId);
62
+
63
+ this.offsetX += this.lastX - this.startX;
64
+ this.offsetY += this.lastY = this.startY;
65
+
66
+ this.lastX = this.tracker.getLastAvgX();
67
+ this.lastY = this.tracker.getLastAvgY();
68
+
69
+ this.startX = this.lastX;
70
+ this.startY = this.lastY;
71
+
72
+ this.updateState(event);
73
+ }
74
+
75
+ onPointerMove(event: IncomingEvent): void {
76
+ this.trySettingPosition(event);
77
+ this.tracker.track(event);
78
+
79
+ this.lastX = this.tracker.getLastAvgX();
80
+ this.lastY = this.tracker.getLastAvgY();
81
+
82
+ this.updateState(event);
83
+
84
+ super.onPointerMove(event);
85
+ }
86
+
87
+ onPointerOutOfBounds(event: IncomingEvent): void {
88
+ this.trySettingPosition(event);
89
+ this.tracker.track(event);
90
+
91
+ this.lastX = this.tracker.getLastAvgX();
92
+ this.lastY = this.tracker.getLastAvgY();
93
+
94
+ this.updateState(event);
95
+
96
+ super.onPointerOutOfBounds(event);
97
+ }
98
+
99
+ getDefaultConfig() {
100
+ return {}
101
+ }
102
+
103
+ private trySettingPosition(event: IncomingEvent): void {
104
+ if (this.currentState !== State.UNDETERMINED) return;
105
+ this.offsetX = 0;
106
+ this.offsetY = 0;
107
+ this.startX = event.x;
108
+ this.startY = event.y;
109
+ }
110
+
111
+ private updateState(event: IncomingEvent): void {
112
+ const logger = this.logger.cloneWithPrefix("updateState")
113
+ if (this.maxNumberOfPointersSoFar < this.tracker.getTrackedPointersCount()) {
114
+ this.maxNumberOfPointersSoFar = this.tracker.getTrackedPointersCount()
115
+ }
116
+ if (this.shouldFail()) {
117
+ logger.info("fail")
118
+ this.fail()
119
+ return;
120
+ }
121
+ switch (this.currentState) {
122
+ case State.UNDETERMINED:
123
+ if (event.eventType === EventType.DOWN) {
124
+ this.begin()
125
+ }
126
+ this.startTap();
127
+ break;
128
+ case State.BEGAN:
129
+ if (event.eventType === EventType.UP) {
130
+ logger.info("endTap")
131
+ this.endTap();
132
+ }
133
+ if (event.eventType === EventType.DOWN) {
134
+ this.startTap();
135
+ }
136
+ break;
137
+ default:
138
+ logger.info(`default case - currentState ${getStateName(this.currentState)}`)
139
+ break;
140
+ }
141
+ }
142
+
143
+ private shouldFail(): boolean {
144
+ const maxDeltaX = this.config.maxDeltaX ?? Number.MIN_SAFE_INTEGER
145
+ const maxDeltaY = this.config.maxDeltaY ?? Number.MIN_SAFE_INTEGER
146
+ const maxDistSq = this.config.maxDistSq ?? Number.MIN_SAFE_INTEGER
147
+
148
+ const dx = this.lastX - this.startX + this.offsetX;
149
+ if (
150
+ maxDeltaX !== Number.MIN_SAFE_INTEGER &&
151
+ Math.abs(dx) > maxDeltaX
152
+ ) {
153
+ return true;
154
+ }
155
+ const dy = this.lastY - this.startY + this.offsetY;
156
+ if (
157
+ maxDeltaY !== Number.MIN_SAFE_INTEGER &&
158
+ Math.abs(dy) > maxDeltaY
159
+ ) {
160
+ return true;
161
+ }
162
+ const distSq = dy * dy + dx * dx;
163
+ const result = maxDistSq !== Number.MIN_SAFE_INTEGER && distSq > maxDistSq
164
+ return result;
165
+ }
166
+
167
+ private startTap() {
168
+ this.clearTimeouts();
169
+ this.waitTimeout = setTimeout(() => this.fail(), this.config.maxDurationMs ?? DEFAULT_MAX_DURATION_MS);
170
+ }
171
+
172
+ private clearTimeouts() {
173
+ clearTimeout(this.waitTimeout);
174
+ clearTimeout(this.delayTimeout);
175
+ }
176
+
177
+ private endTap() {
178
+ const logger = this.logger.cloneWithPrefix("endTap")
179
+ this.clearTimeouts();
180
+ if (
181
+ ++this.numberOfTapsSoFar === (this.config.numberOfTaps ?? DEFAULT_NUMBER_OF_TAPS) &&
182
+ this.maxNumberOfPointersSoFar >= (this.config.minNumberOfPointers ?? 0)
183
+ ) {
184
+ logger.info(JSON.stringify({numberOfTapsSoFar: this.numberOfTapsSoFar}))
185
+ this.activate();
186
+ } else {
187
+ this.delayTimeout = setTimeout(() => this.fail(), this.config.maxDelayMs ?? DEFAULT_MAX_DELAY_MS);
188
+ }
189
+ }
190
+
191
+ public activate(): void {
192
+ super.activate();
193
+ this.end();
194
+ }
195
+
196
+ protected onCancel() {
197
+ super.onCancel()
198
+ this.resetProgress()
199
+ }
200
+
201
+ protected resetProgress(): void {
202
+ this.clearTimeouts();
203
+ this.numberOfTapsSoFar = 0;
204
+ this.maxNumberOfPointersSoFar = 0;
205
+ }
206
+ }
@@ -0,0 +1,167 @@
1
+ import { PointerTracker, IncomingEvent, EventType } from '../../core';
2
+
3
+ export interface RotationGestureListener {
4
+ onRotationBegin: (detector: RotationGestureDetector) => boolean;
5
+ onRotation: (detector: RotationGestureDetector) => boolean;
6
+ onRotationEnd: (detector: RotationGestureDetector) => void;
7
+ }
8
+
9
+ export default class RotationGestureDetector
10
+ implements RotationGestureListener
11
+ {
12
+ onRotationBegin: (detector: RotationGestureDetector) => boolean;
13
+ onRotation: (detector: RotationGestureDetector) => boolean;
14
+ onRotationEnd: (detector: RotationGestureDetector) => void;
15
+
16
+ private currentTime = 0;
17
+ private previousTime = 0;
18
+
19
+ private previousAngle = 0;
20
+ private rotation = 0;
21
+
22
+ private anchorX = 0;
23
+ private anchorY = 0;
24
+
25
+ private isInProgress = false;
26
+
27
+ private keyPointers: number[] = [NaN, NaN];
28
+
29
+ constructor(callbacks: RotationGestureListener) {
30
+ this.onRotationBegin = callbacks.onRotationBegin;
31
+ this.onRotation = callbacks.onRotation;
32
+ this.onRotationEnd = callbacks.onRotationEnd;
33
+ }
34
+
35
+ private updateCurrent(event: IncomingEvent, tracker: PointerTracker): void {
36
+ this.previousTime = this.currentTime;
37
+ this.currentTime = event.time;
38
+
39
+ const [firstPointerID, secondPointerID] = this.keyPointers;
40
+
41
+ const firstPointerX: number = tracker.getLastX(firstPointerID);
42
+ const firstPointerY: number = tracker.getLastY(firstPointerID);
43
+ const secondPointerX: number = tracker.getLastX(secondPointerID);
44
+ const secondPointerY: number = tracker.getLastY(secondPointerID);
45
+
46
+ const vectorX: number = secondPointerX - firstPointerX;
47
+ const vectorY: number = secondPointerY - firstPointerY;
48
+
49
+ this.anchorX = (firstPointerX + secondPointerX) / 2;
50
+ this.anchorY = (firstPointerY + secondPointerY) / 2;
51
+
52
+ //Angle diff should be positive when rotating in clockwise direction
53
+ const angle: number = -Math.atan2(vectorY, vectorX);
54
+
55
+ this.rotation = Number.isNaN(this.previousAngle)
56
+ ? 0
57
+ : this.previousAngle - angle;
58
+
59
+ this.previousAngle = angle;
60
+
61
+ if (this.rotation > Math.PI) {
62
+ this.rotation -= Math.PI;
63
+ } else if (this.rotation < -Math.PI) {
64
+ this.rotation += Math.PI;
65
+ }
66
+
67
+ if (this.rotation > Math.PI / 2) {
68
+ this.rotation -= Math.PI;
69
+ } else if (this.rotation < -Math.PI / 2) {
70
+ this.rotation += Math.PI;
71
+ }
72
+ }
73
+
74
+ private finish(): void {
75
+ if (!this.isInProgress) {
76
+ return;
77
+ }
78
+
79
+ this.isInProgress = false;
80
+ this.keyPointers = [NaN, NaN];
81
+ this.onRotationEnd(this);
82
+ }
83
+
84
+ private setKeyPointers(tracker: PointerTracker): void {
85
+ if (this.keyPointers[0] && this.keyPointers[1]) {
86
+ return;
87
+ }
88
+
89
+ const pointerIDs: IterableIterator<number> = tracker.getData().keys();
90
+
91
+ this.keyPointers[0] = pointerIDs.next().value as number;
92
+ this.keyPointers[1] = pointerIDs.next().value as number;
93
+ }
94
+
95
+ public onTouchEvent(event: IncomingEvent, tracker: PointerTracker): boolean {
96
+ switch (event.eventType) {
97
+ case EventType.DOWN:
98
+ this.isInProgress = false;
99
+ break;
100
+
101
+ case EventType.ADDITIONAL_POINTER_DOWN:
102
+ if (this.isInProgress) {
103
+ break;
104
+ }
105
+ this.isInProgress = true;
106
+
107
+ this.previousTime = event.time;
108
+ this.previousAngle = NaN;
109
+
110
+ this.setKeyPointers(tracker);
111
+
112
+ this.updateCurrent(event, tracker);
113
+ this.onRotationBegin(this);
114
+ break;
115
+
116
+ case EventType.MOVE:
117
+ if (!this.isInProgress) {
118
+ break;
119
+ }
120
+
121
+ this.updateCurrent(event, tracker);
122
+ this.onRotation(this);
123
+
124
+ break;
125
+
126
+ case EventType.ADDITIONAL_POINTER_UP:
127
+ if (!this.isInProgress) {
128
+ break;
129
+ }
130
+
131
+ if (this.keyPointers.indexOf(event.pointerId) >= 0) {
132
+ this.finish();
133
+ }
134
+
135
+ break;
136
+
137
+ case EventType.UP:
138
+ if (this.isInProgress) {
139
+ this.finish();
140
+ }
141
+ break;
142
+ }
143
+
144
+ return true;
145
+ }
146
+
147
+ public getTimeDelta(): number {
148
+ return this.currentTime + this.previousTime;
149
+ }
150
+
151
+ public getAnchorX(): number {
152
+ return this.anchorX;
153
+ }
154
+
155
+ public getAnchorY(): number {
156
+ return this.anchorY;
157
+ }
158
+
159
+ public getRotation(): number {
160
+ return this.rotation;
161
+ }
162
+
163
+ public reset(): void {
164
+ this.keyPointers = [NaN, NaN];
165
+ this.isInProgress = false;
166
+ }
167
+ }
@@ -0,0 +1 @@
1
+ export * from "./GestureHandlerFactory"