@react-native-oh-tpl/react-native-gesture-handler 2.12.6-1 → 2.12.6-2

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 (79) hide show
  1. package/harmony/gesture_handler/LICENSE +21 -0
  2. package/harmony/gesture_handler/OAT.xml +44 -0
  3. package/harmony/gesture_handler/README.OpenSource +11 -0
  4. package/harmony/gesture_handler/README.md +1 -0
  5. package/harmony/gesture_handler/build-profile.json5 +7 -7
  6. package/harmony/gesture_handler/hvigorfile.ts +2 -2
  7. package/harmony/gesture_handler/index.ets +2 -2
  8. package/harmony/gesture_handler/oh-package.json5 +13 -11
  9. package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -8
  10. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +33 -33
  11. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +14 -14
  12. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonComponentDescriptor.h +60 -60
  13. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.cpp +17 -17
  14. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.h +11 -11
  15. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentDescriptor.h +60 -60
  16. package/harmony/gesture_handler/src/main/ets/CircularBuffer.ts +42 -42
  17. package/harmony/gesture_handler/src/main/ets/Event.ts +67 -67
  18. package/harmony/gesture_handler/src/main/ets/EventDispatcher.ts +37 -37
  19. package/harmony/gesture_handler/src/main/ets/GestureHandler.ts +663 -663
  20. package/harmony/gesture_handler/src/main/ets/GestureHandlerArkUIAdapter.ets +201 -201
  21. package/harmony/gesture_handler/src/main/ets/GestureHandlerFactory.ts +44 -44
  22. package/harmony/gesture_handler/src/main/ets/GestureHandlerOrchestrator.ts +280 -280
  23. package/harmony/gesture_handler/src/main/ets/GestureHandlerPackage.ts +22 -22
  24. package/harmony/gesture_handler/src/main/ets/GestureHandlerRegistry.ts +27 -27
  25. package/harmony/gesture_handler/src/main/ets/InteractionManager.ts +108 -108
  26. package/harmony/gesture_handler/src/main/ets/LeastSquareSolver.ts +182 -182
  27. package/harmony/gesture_handler/src/main/ets/NativeViewGestureHandler.ts +114 -114
  28. package/harmony/gesture_handler/src/main/ets/OutgoingEvent.ts +33 -33
  29. package/harmony/gesture_handler/src/main/ets/PanGestureHandler.ts +327 -327
  30. package/harmony/gesture_handler/src/main/ets/PointerTracker.ts +239 -239
  31. package/harmony/gesture_handler/src/main/ets/RNGHError.ts +4 -4
  32. package/harmony/gesture_handler/src/main/ets/RNGHLogger.ts +28 -28
  33. package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandler.ets +57 -57
  34. package/harmony/gesture_handler/src/main/ets/RNGestureHandlerButton.ets +36 -36
  35. package/harmony/gesture_handler/src/main/ets/RNGestureHandlerModule.ts +125 -125
  36. package/harmony/gesture_handler/src/main/ets/RNGestureHandlerRootView.ets +56 -55
  37. package/harmony/gesture_handler/src/main/ets/RNOHScrollLocker.ts +10 -10
  38. package/harmony/gesture_handler/src/main/ets/State.ts +46 -46
  39. package/harmony/gesture_handler/src/main/ets/TapGestureHandler.ts +205 -205
  40. package/harmony/gesture_handler/src/main/ets/Vector2D.ts +36 -36
  41. package/harmony/gesture_handler/src/main/ets/VelocityTracker.ts +98 -98
  42. package/harmony/gesture_handler/src/main/ets/View.ts +70 -70
  43. package/harmony/gesture_handler/src/main/ets/ViewRegistry.ts +42 -42
  44. package/harmony/gesture_handler/src/main/ets/pages/Index.ets +16 -16
  45. package/harmony/gesture_handler/src/main/ets/webviewability/WebviewAbility.ts +41 -41
  46. package/harmony/gesture_handler/src/main/module.json5 +6 -6
  47. package/harmony/gesture_handler/src/main/resources/base/element/color.json +7 -7
  48. package/harmony/gesture_handler/src/main/resources/base/element/string.json +15 -15
  49. package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -5
  50. package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +15 -15
  51. package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +15 -15
  52. package/harmony/gesture_handler.har +0 -0
  53. package/lib/commonjs/components/touchables/GenericTouchable.js +9 -9
  54. package/lib/commonjs/components/touchables/TouchableOpacity.js +2 -2
  55. package/lib/commonjs/handlers/createNativeWrapper.js +6 -6
  56. package/lib/commonjs/handlers/gestures/GestureDetector.js +3 -3
  57. package/lib/module/components/touchables/GenericTouchable.js +9 -9
  58. package/lib/module/components/touchables/TouchableOpacity.js +2 -2
  59. package/lib/module/handlers/createNativeWrapper.js +6 -6
  60. package/lib/module/handlers/gestures/GestureDetector.js +3 -3
  61. package/package.json +70 -70
  62. package/src/RNGestureHandlerModule.ts +6 -6
  63. package/src/components/GestureButtons.tsx +334 -334
  64. package/src/components/GestureHandlerButton.tsx +5 -5
  65. package/src/components/GestureHandlerRootView.tsx +34 -34
  66. package/src/components/RNGestureHandlerButton.tsx +23 -23
  67. package/src/components/touchables/GenericTouchable.tsx +301 -301
  68. package/src/components/touchables/TouchableOpacity.tsx +76 -76
  69. package/src/components/touchables/TouchableWithoutFeedback.tsx +14 -14
  70. package/src/components/touchables/index.ts +7 -7
  71. package/src/handlers/NativeViewGestureHandler.ts +55 -55
  72. package/src/handlers/PanGestureHandler.ts +327 -327
  73. package/src/handlers/TapGestureHandler.ts +95 -95
  74. package/src/handlers/createHandler.tsx +535 -535
  75. package/src/handlers/createNativeWrapper.tsx +81 -81
  76. package/src/handlers/gestureHandlerCommon.ts +15 -15
  77. package/src/handlers/gestures/GestureDetector.tsx +823 -823
  78. package/src/index.ts +172 -172
  79. package/src/init.ts +18 -18
@@ -1,206 +1,206 @@
1
- import { GestureHandler, GestureHandlerDependencies } from "./GestureHandler"
2
- import { AdaptedEvent, EventType } from "./Event"
3
- import { State, getStateName } from "./State"
4
-
5
- const DEFAULT_MAX_DURATION_MS = 500;
6
- const DEFAULT_NUMBER_OF_TAPS = 1;
7
- const DEFAULT_MAX_DELAY_MS = 500;
8
-
9
- export class TapGestureHandler extends GestureHandler {
10
- private startX = 0;
11
- private startY = 0;
12
- private offsetX = 0;
13
- private offsetY = 0;
14
- private lastX = 0;
15
- private lastY = 0;
16
- private maxNumberOfPointersSoFar = 0;
17
- private numberOfTapsSoFar: number = 0;
18
- private waitTimeout: number | undefined;
19
- private delayTimeout: number | undefined;
20
-
21
- constructor(deps: GestureHandlerDependencies) {
22
- super({...deps, logger: deps.logger.cloneWithPrefix("TapGestureHandler")})
23
- }
24
-
25
- onPointerDown(event) {
26
- this.tracker.addToTracker(event);
27
- super.onPointerDown(event);
28
- this.trySettingPosition(event);
29
- this.lastX = event.x;
30
- this.lastY = event.y;
31
- this.updateState(event);
32
- }
33
-
34
- onAdditionalPointerAdd(event: AdaptedEvent): void {
35
- super.onAdditionalPointerAdd(event);
36
- this.tracker.addToTracker(event);
37
- this.trySettingPosition(event);
38
-
39
- this.offsetX += this.lastX - this.startX;
40
- this.offsetY += this.lastY - this.startY;
41
-
42
- this.lastX = this.tracker.getLastAvgX();
43
- this.lastY = this.tracker.getLastAvgY();
44
-
45
- this.startX = this.tracker.getLastAvgX();
46
- this.startY = this.tracker.getLastAvgY();
47
-
48
- this.updateState(event);
49
- }
50
-
51
- onPointerUp(event: AdaptedEvent): void {
52
- super.onPointerUp(event);
53
- this.lastX = this.tracker.getLastAvgX();
54
- this.lastY = this.tracker.getLastAvgY();
55
-
56
- this.tracker.removeFromTracker(event.pointerId);
57
-
58
- this.updateState(event);
59
- }
60
-
61
- onAdditionalPointerRemove(event: AdaptedEvent): void {
62
- super.onAdditionalPointerRemove(event);
63
- this.tracker.removeFromTracker(event.pointerId);
64
-
65
- this.offsetX += this.lastX - this.startX;
66
- this.offsetY += this.lastY = this.startY;
67
-
68
- this.lastX = this.tracker.getLastAvgX();
69
- this.lastY = this.tracker.getLastAvgY();
70
-
71
- this.startX = this.lastX;
72
- this.startY = this.lastY;
73
-
74
- this.updateState(event);
75
- }
76
-
77
- onPointerMove(event: AdaptedEvent): void {
78
- this.trySettingPosition(event);
79
- this.tracker.track(event);
80
-
81
- this.lastX = this.tracker.getLastAvgX();
82
- this.lastY = this.tracker.getLastAvgY();
83
-
84
- this.updateState(event);
85
-
86
- super.onPointerMove(event);
87
- }
88
-
89
- onPointerOutOfBounds(event: AdaptedEvent): void {
90
- this.trySettingPosition(event);
91
- this.tracker.track(event);
92
-
93
- this.lastX = this.tracker.getLastAvgX();
94
- this.lastY = this.tracker.getLastAvgY();
95
-
96
- this.updateState(event);
97
-
98
- super.onPointerOutOfBounds(event);
99
- }
100
-
101
- getDefaultConfig() {
102
- return {}
103
- }
104
-
105
- private trySettingPosition(event: AdaptedEvent): void {
106
- if (this.currentState !== State.UNDETERMINED) return;
107
- this.offsetX = 0;
108
- this.offsetY = 0;
109
- this.startX = event.x;
110
- this.startY = event.y;
111
- }
112
-
113
- private updateState(event: AdaptedEvent): void {
114
- const logger = this.logger.cloneWithPrefix("updateState")
115
- if (this.maxNumberOfPointersSoFar < this.tracker.getTrackedPointersCount()) {
116
- this.maxNumberOfPointersSoFar = this.tracker.getTrackedPointersCount()
117
- }
118
- if (this.shouldFail()) {
119
- logger.info("fail")
120
- this.fail()
121
- return;
122
- }
123
- switch (this.currentState) {
124
- case State.UNDETERMINED:
125
- if (event.eventType === EventType.DOWN) {
126
- this.begin()
127
- }
128
- this.startTap();
129
- break;
130
- case State.BEGAN:
131
- if (event.eventType === EventType.UP) {
132
- logger.info("endTap")
133
- this.endTap();
134
- }
135
- if (event.eventType === EventType.DOWN) {
136
- this.startTap();
137
- }
138
- break;
139
- default:
140
- logger.info(`default case - currentState ${getStateName(this.currentState)}`)
141
- break;
142
- }
143
- }
144
-
145
- private shouldFail(): boolean {
146
- const maxDeltaX = this.config.maxDeltaX ?? Number.MIN_SAFE_INTEGER
147
- const maxDeltaY = this.config.maxDeltaY ?? Number.MIN_SAFE_INTEGER
148
- const maxDistSq = this.config.maxDistSq ?? Number.MIN_SAFE_INTEGER
149
-
150
- const dx = this.lastX - this.startX + this.offsetX;
151
- if (
152
- maxDeltaX !== Number.MIN_SAFE_INTEGER &&
153
- Math.abs(dx) > maxDeltaX
154
- ) {
155
- return true;
156
- }
157
- const dy = this.lastY - this.startY + this.offsetY;
158
- if (
159
- maxDeltaY !== Number.MIN_SAFE_INTEGER &&
160
- Math.abs(dy) > maxDeltaY
161
- ) {
162
- return true;
163
- }
164
- const distSq = dy * dy + dx * dx;
165
- const result = maxDistSq !== Number.MIN_SAFE_INTEGER && distSq > maxDistSq
166
- return result;
167
- }
168
-
169
- private startTap() {
170
- this.clearTimeouts();
171
- this.waitTimeout = setTimeout(() => this.fail(), this.config.maxDurationMs ?? DEFAULT_MAX_DURATION_MS);
172
- }
173
-
174
- private clearTimeouts() {
175
- clearTimeout(this.waitTimeout);
176
- clearTimeout(this.delayTimeout);
177
- }
178
-
179
- private endTap() {
180
- this.clearTimeouts();
181
- if (
182
- ++this.numberOfTapsSoFar === (this.config.numberOfTaps ?? DEFAULT_NUMBER_OF_TAPS) &&
183
- this.maxNumberOfPointersSoFar >= (this.config.minNumberOfPointers ?? 0)
184
- ) {
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
- }
1
+ import { GestureHandler, GestureHandlerDependencies } from "./GestureHandler"
2
+ import { AdaptedEvent, EventType } from "./Event"
3
+ import { State, getStateName } from "./State"
4
+
5
+ const DEFAULT_MAX_DURATION_MS = 500;
6
+ const DEFAULT_NUMBER_OF_TAPS = 1;
7
+ const DEFAULT_MAX_DELAY_MS = 500;
8
+
9
+ export class TapGestureHandler extends GestureHandler {
10
+ private startX = 0;
11
+ private startY = 0;
12
+ private offsetX = 0;
13
+ private offsetY = 0;
14
+ private lastX = 0;
15
+ private lastY = 0;
16
+ private maxNumberOfPointersSoFar = 0;
17
+ private numberOfTapsSoFar: number = 0;
18
+ private waitTimeout: number | undefined;
19
+ private delayTimeout: number | undefined;
20
+
21
+ constructor(deps: GestureHandlerDependencies) {
22
+ super({...deps, logger: deps.logger.cloneWithPrefix("TapGestureHandler")})
23
+ }
24
+
25
+ onPointerDown(event) {
26
+ this.tracker.addToTracker(event);
27
+ super.onPointerDown(event);
28
+ this.trySettingPosition(event);
29
+ this.lastX = event.x;
30
+ this.lastY = event.y;
31
+ this.updateState(event);
32
+ }
33
+
34
+ onAdditionalPointerAdd(event: AdaptedEvent): void {
35
+ super.onAdditionalPointerAdd(event);
36
+ this.tracker.addToTracker(event);
37
+ this.trySettingPosition(event);
38
+
39
+ this.offsetX += this.lastX - this.startX;
40
+ this.offsetY += this.lastY - this.startY;
41
+
42
+ this.lastX = this.tracker.getLastAvgX();
43
+ this.lastY = this.tracker.getLastAvgY();
44
+
45
+ this.startX = this.tracker.getLastAvgX();
46
+ this.startY = this.tracker.getLastAvgY();
47
+
48
+ this.updateState(event);
49
+ }
50
+
51
+ onPointerUp(event: AdaptedEvent): void {
52
+ super.onPointerUp(event);
53
+ this.lastX = this.tracker.getLastAvgX();
54
+ this.lastY = this.tracker.getLastAvgY();
55
+
56
+ this.tracker.removeFromTracker(event.pointerId);
57
+
58
+ this.updateState(event);
59
+ }
60
+
61
+ onAdditionalPointerRemove(event: AdaptedEvent): void {
62
+ super.onAdditionalPointerRemove(event);
63
+ this.tracker.removeFromTracker(event.pointerId);
64
+
65
+ this.offsetX += this.lastX - this.startX;
66
+ this.offsetY += this.lastY = this.startY;
67
+
68
+ this.lastX = this.tracker.getLastAvgX();
69
+ this.lastY = this.tracker.getLastAvgY();
70
+
71
+ this.startX = this.lastX;
72
+ this.startY = this.lastY;
73
+
74
+ this.updateState(event);
75
+ }
76
+
77
+ onPointerMove(event: AdaptedEvent): void {
78
+ this.trySettingPosition(event);
79
+ this.tracker.track(event);
80
+
81
+ this.lastX = this.tracker.getLastAvgX();
82
+ this.lastY = this.tracker.getLastAvgY();
83
+
84
+ this.updateState(event);
85
+
86
+ super.onPointerMove(event);
87
+ }
88
+
89
+ onPointerOutOfBounds(event: AdaptedEvent): void {
90
+ this.trySettingPosition(event);
91
+ this.tracker.track(event);
92
+
93
+ this.lastX = this.tracker.getLastAvgX();
94
+ this.lastY = this.tracker.getLastAvgY();
95
+
96
+ this.updateState(event);
97
+
98
+ super.onPointerOutOfBounds(event);
99
+ }
100
+
101
+ getDefaultConfig() {
102
+ return {}
103
+ }
104
+
105
+ private trySettingPosition(event: AdaptedEvent): void {
106
+ if (this.currentState !== State.UNDETERMINED) return;
107
+ this.offsetX = 0;
108
+ this.offsetY = 0;
109
+ this.startX = event.x;
110
+ this.startY = event.y;
111
+ }
112
+
113
+ private updateState(event: AdaptedEvent): void {
114
+ const logger = this.logger.cloneWithPrefix("updateState")
115
+ if (this.maxNumberOfPointersSoFar < this.tracker.getTrackedPointersCount()) {
116
+ this.maxNumberOfPointersSoFar = this.tracker.getTrackedPointersCount()
117
+ }
118
+ if (this.shouldFail()) {
119
+ logger.info("fail")
120
+ this.fail()
121
+ return;
122
+ }
123
+ switch (this.currentState) {
124
+ case State.UNDETERMINED:
125
+ if (event.eventType === EventType.DOWN) {
126
+ this.begin()
127
+ }
128
+ this.startTap();
129
+ break;
130
+ case State.BEGAN:
131
+ if (event.eventType === EventType.UP) {
132
+ logger.info("endTap")
133
+ this.endTap();
134
+ }
135
+ if (event.eventType === EventType.DOWN) {
136
+ this.startTap();
137
+ }
138
+ break;
139
+ default:
140
+ logger.info(`default case - currentState ${getStateName(this.currentState)}`)
141
+ break;
142
+ }
143
+ }
144
+
145
+ private shouldFail(): boolean {
146
+ const maxDeltaX = this.config.maxDeltaX ?? Number.MIN_SAFE_INTEGER
147
+ const maxDeltaY = this.config.maxDeltaY ?? Number.MIN_SAFE_INTEGER
148
+ const maxDistSq = this.config.maxDistSq ?? Number.MIN_SAFE_INTEGER
149
+
150
+ const dx = this.lastX - this.startX + this.offsetX;
151
+ if (
152
+ maxDeltaX !== Number.MIN_SAFE_INTEGER &&
153
+ Math.abs(dx) > maxDeltaX
154
+ ) {
155
+ return true;
156
+ }
157
+ const dy = this.lastY - this.startY + this.offsetY;
158
+ if (
159
+ maxDeltaY !== Number.MIN_SAFE_INTEGER &&
160
+ Math.abs(dy) > maxDeltaY
161
+ ) {
162
+ return true;
163
+ }
164
+ const distSq = dy * dy + dx * dx;
165
+ const result = maxDistSq !== Number.MIN_SAFE_INTEGER && distSq > maxDistSq
166
+ return result;
167
+ }
168
+
169
+ private startTap() {
170
+ this.clearTimeouts();
171
+ this.waitTimeout = setTimeout(() => this.fail(), this.config.maxDurationMs ?? DEFAULT_MAX_DURATION_MS);
172
+ }
173
+
174
+ private clearTimeouts() {
175
+ clearTimeout(this.waitTimeout);
176
+ clearTimeout(this.delayTimeout);
177
+ }
178
+
179
+ private endTap() {
180
+ this.clearTimeouts();
181
+ if (
182
+ ++this.numberOfTapsSoFar === (this.config.numberOfTaps ?? DEFAULT_NUMBER_OF_TAPS) &&
183
+ this.maxNumberOfPointersSoFar >= (this.config.minNumberOfPointers ?? 0)
184
+ ) {
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
206
  }
@@ -1,36 +1,36 @@
1
- export class Vector2D {
2
- constructor(
3
- private val: {
4
- x: number;
5
- y: number;
6
- } = {x: 0, y: 0},
7
- ) {}
8
-
9
- get x() {
10
- return this.val.x;
11
- }
12
-
13
- get y() {
14
- return this.val.y;
15
- }
16
-
17
- get value() {
18
- return {...this.val};
19
- }
20
-
21
- public clone() {
22
- return new Vector2D({...this.val});
23
- }
24
-
25
- public subtract(vec: Vector2D) {
26
- this.val.x -= vec.x;
27
- this.val.y -= vec.y;
28
- return this;
29
- }
30
-
31
- public add(vec: Vector2D) {
32
- this.val.x += vec.x;
33
- this.val.y += vec.y;
34
- return this;
35
- }
36
- }
1
+ export class Vector2D {
2
+ constructor(
3
+ private val: {
4
+ x: number;
5
+ y: number;
6
+ } = {x: 0, y: 0},
7
+ ) {}
8
+
9
+ get x() {
10
+ return this.val.x;
11
+ }
12
+
13
+ get y() {
14
+ return this.val.y;
15
+ }
16
+
17
+ get value() {
18
+ return {...this.val};
19
+ }
20
+
21
+ public clone() {
22
+ return new Vector2D({...this.val});
23
+ }
24
+
25
+ public subtract(vec: Vector2D) {
26
+ this.val.x -= vec.x;
27
+ this.val.y -= vec.y;
28
+ return this;
29
+ }
30
+
31
+ public add(vec: Vector2D) {
32
+ this.val.x += vec.x;
33
+ this.val.y += vec.y;
34
+ return this;
35
+ }
36
+ }
@@ -1,98 +1,98 @@
1
- import { AdaptedEvent } from './Event';
2
- import { CircularBuffer } from './CircularBuffer';
3
- import { LeastSquareSolver } from './LeastSquareSolver';
4
-
5
- export default class VelocityTracker {
6
- private assumePointerMoveStoppedMilliseconds = 40;
7
- private historySize = 20;
8
- private horizonMilliseconds = 300;
9
- private minSampleSize = 3;
10
-
11
- private samples: CircularBuffer<AdaptedEvent>;
12
-
13
- constructor() {
14
- this.samples = new CircularBuffer<AdaptedEvent>(this.historySize);
15
- }
16
-
17
- public add(event: AdaptedEvent): void {
18
- this.samples.push(event);
19
- }
20
-
21
- /// Returns an estimate of the velocity of the object being tracked by the
22
- /// tracker given the current information available to the tracker.
23
- ///
24
- /// Information is added using [addPosition].
25
- ///
26
- /// Returns null if there is no data on which to base an estimate.
27
- private getVelocityEstimate(): [number, number] | null {
28
- const x = [];
29
- const y = [];
30
- const w = [];
31
- const time = [];
32
-
33
- let sampleCount = 0;
34
- let index = this.samples.size - 1;
35
- const newestSample = this.samples.get(index);
36
- if (!newestSample) {
37
- return null;
38
- }
39
-
40
- let previousSample = newestSample;
41
-
42
- // Starting with the most recent PointAtTime sample, iterate backwards while
43
- // the samples represent continuous motion.
44
- while (sampleCount < this.samples.size) {
45
- const sample = this.samples.get(index);
46
-
47
- const age = newestSample.time - sample.time;
48
- const delta = Math.abs(sample.time - previousSample.time);
49
- previousSample = sample;
50
-
51
- if (
52
- age > this.horizonMilliseconds ||
53
- delta > this.assumePointerMoveStoppedMilliseconds
54
- ) {
55
- break;
56
- }
57
-
58
- x.push(sample.x);
59
- y.push(sample.y);
60
- w.push(1);
61
- time.push(-age);
62
-
63
- sampleCount++;
64
- index--;
65
- }
66
-
67
- if (sampleCount >= this.minSampleSize) {
68
- const xSolver = new LeastSquareSolver(time, x, w);
69
- const xFit = xSolver.solve(2);
70
-
71
- if (xFit !== null) {
72
- const ySolver = new LeastSquareSolver(time, y, w);
73
- const yFit = ySolver.solve(2);
74
-
75
- if (yFit !== null) {
76
- const xVelocity = xFit.coefficients[1] * 1000;
77
- const yVelocity = yFit.coefficients[1] * 1000;
78
-
79
- return [xVelocity, yVelocity];
80
- }
81
- }
82
- }
83
-
84
- return null;
85
- }
86
-
87
- public getVelocity(): [number, number] {
88
- const estimate = this.getVelocityEstimate();
89
- if (estimate !== null) {
90
- return estimate;
91
- }
92
- return [0, 0];
93
- }
94
-
95
- public reset(): void {
96
- this.samples.clear();
97
- }
98
- }
1
+ import { AdaptedEvent } from './Event';
2
+ import { CircularBuffer } from './CircularBuffer';
3
+ import { LeastSquareSolver } from './LeastSquareSolver';
4
+
5
+ export default class VelocityTracker {
6
+ private assumePointerMoveStoppedMilliseconds = 40;
7
+ private historySize = 20;
8
+ private horizonMilliseconds = 300;
9
+ private minSampleSize = 3;
10
+
11
+ private samples: CircularBuffer<AdaptedEvent>;
12
+
13
+ constructor() {
14
+ this.samples = new CircularBuffer<AdaptedEvent>(this.historySize);
15
+ }
16
+
17
+ public add(event: AdaptedEvent): void {
18
+ this.samples.push(event);
19
+ }
20
+
21
+ /// Returns an estimate of the velocity of the object being tracked by the
22
+ /// tracker given the current information available to the tracker.
23
+ ///
24
+ /// Information is added using [addPosition].
25
+ ///
26
+ /// Returns null if there is no data on which to base an estimate.
27
+ private getVelocityEstimate(): [number, number] | null {
28
+ const x = [];
29
+ const y = [];
30
+ const w = [];
31
+ const time = [];
32
+
33
+ let sampleCount = 0;
34
+ let index = this.samples.size - 1;
35
+ const newestSample = this.samples.get(index);
36
+ if (!newestSample) {
37
+ return null;
38
+ }
39
+
40
+ let previousSample = newestSample;
41
+
42
+ // Starting with the most recent PointAtTime sample, iterate backwards while
43
+ // the samples represent continuous motion.
44
+ while (sampleCount < this.samples.size) {
45
+ const sample = this.samples.get(index);
46
+
47
+ const age = newestSample.time - sample.time;
48
+ const delta = Math.abs(sample.time - previousSample.time);
49
+ previousSample = sample;
50
+
51
+ if (
52
+ age > this.horizonMilliseconds ||
53
+ delta > this.assumePointerMoveStoppedMilliseconds
54
+ ) {
55
+ break;
56
+ }
57
+
58
+ x.push(sample.x);
59
+ y.push(sample.y);
60
+ w.push(1);
61
+ time.push(-age);
62
+
63
+ sampleCount++;
64
+ index--;
65
+ }
66
+
67
+ if (sampleCount >= this.minSampleSize) {
68
+ const xSolver = new LeastSquareSolver(time, x, w);
69
+ const xFit = xSolver.solve(2);
70
+
71
+ if (xFit !== null) {
72
+ const ySolver = new LeastSquareSolver(time, y, w);
73
+ const yFit = ySolver.solve(2);
74
+
75
+ if (yFit !== null) {
76
+ const xVelocity = xFit.coefficients[1] * 1000;
77
+ const yVelocity = yFit.coefficients[1] * 1000;
78
+
79
+ return [xVelocity, yVelocity];
80
+ }
81
+ }
82
+ }
83
+
84
+ return null;
85
+ }
86
+
87
+ public getVelocity(): [number, number] {
88
+ const estimate = this.getVelocityEstimate();
89
+ if (estimate !== null) {
90
+ return estimate;
91
+ }
92
+ return [0, 0];
93
+ }
94
+
95
+ public reset(): void {
96
+ this.samples.clear();
97
+ }
98
+ }