@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.
- package/DrawerLayout/index.ts +2 -2
- package/Swipeable/index.ts +2 -2
- package/harmony/gesture_handler/BuildProfile.ets +17 -0
- package/harmony/gesture_handler/build-profile.json5 +19 -0
- package/harmony/gesture_handler/hvigorfile.ts +2 -0
- package/harmony/gesture_handler/index.ets +3 -0
- package/harmony/gesture_handler/oh-package-lock.json5 +18 -0
- package/harmony/gesture_handler/oh-package.json5 +12 -0
- package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +8 -0
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +149 -0
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +21 -0
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonComponentDescriptor.h +36 -0
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerButtonJSIBinder.h +32 -0
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.cpp +22 -0
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerModule.h +15 -0
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentDescriptor.h +36 -0
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewJSIBinder.h +25 -0
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +27 -0
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +242 -0
- package/harmony/gesture_handler/src/main/ets/core/CircularBuffer.ts +42 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +690 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +335 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +63 -0
- package/harmony/gesture_handler/src/main/ets/core/IncomingEvent.ts +78 -0
- package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
- package/harmony/gesture_handler/src/main/ets/core/LeastSquareSolver.ts +182 -0
- package/harmony/gesture_handler/src/main/ets/core/OutgoingEvent.ts +34 -0
- package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
- package/harmony/gesture_handler/src/main/ets/core/PointerTracker.ts +239 -0
- package/harmony/gesture_handler/src/main/ets/core/RNGHError.ts +5 -0
- package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +12 -0
- package/harmony/gesture_handler/src/main/ets/core/State.ts +47 -0
- package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
- package/harmony/gesture_handler/src/main/ets/core/VelocityTracker.ts +106 -0
- package/harmony/gesture_handler/src/main/ets/core/View.ts +21 -0
- package/harmony/gesture_handler/src/main/ets/core/ViewFinder.ts +11 -0
- package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +8 -0
- package/harmony/gesture_handler/src/main/ets/core/index.ts +15 -0
- package/harmony/gesture_handler/src/main/ets/detectors/ScaleGestureDetector.ts +169 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +211 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +64 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +127 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +42 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +115 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +342 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +159 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +164 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +206 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts +167 -0
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/index.ts +1 -0
- package/harmony/gesture_handler/src/main/ets/namespace/RNGestureHandlerModule.ts +24 -0
- package/harmony/gesture_handler/src/main/ets/namespace/components/RNGestureHandlerButton.ts +139 -0
- package/harmony/gesture_handler/src/main/ets/namespace/components/RNGestureHandlerRootView.ts +101 -0
- package/harmony/gesture_handler/src/main/ets/namespace/components/ts.ts +2 -0
- package/harmony/gesture_handler/src/main/ets/namespace/ts.ts +2 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerArkUIAdapter.ts +240 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +22 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +49 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +71 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerArkTS.ts +98 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +110 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerButton.ets +38 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +233 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerRootView.ets +53 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +24 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +32 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/View.ts +134 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +97 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/types.ts +25 -0
- package/harmony/gesture_handler/src/main/module.json5 +9 -0
- package/harmony/gesture_handler/src/main/resources/base/element/color.json +8 -0
- package/harmony/gesture_handler/src/main/resources/base/element/string.json +16 -0
- package/harmony/gesture_handler/src/main/resources/base/media/icon.png +0 -0
- package/harmony/gesture_handler/src/main/resources/base/profile/main_pages.json +5 -0
- package/harmony/gesture_handler/src/main/resources/en_US/element/string.json +16 -0
- package/harmony/gesture_handler/src/main/resources/zh_CN/element/string.json +16 -0
- package/harmony/gesture_handler/ts.ts +2 -0
- package/harmony/gesture_handler.har +0 -0
- package/lib/commonjs/RNGestureHandlerModule.js +3 -2
- package/lib/commonjs/RNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/components/GestureHandlerRootView.js +3 -3
- package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
- package/lib/commonjs/handlers/createHandler.js +18 -15
- package/lib/commonjs/handlers/createHandler.js.map +1 -1
- package/lib/commonjs/index.js +36 -8
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeRNGestureHandlerModule.js +2 -1
- package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
- package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js +3 -2
- package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js +3 -2
- package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/module/RNGestureHandlerModule.js.map +1 -1
- package/lib/module/components/GestureHandlerRootView.js.map +1 -1
- package/lib/module/handlers/createHandler.js +15 -12
- package/lib/module/handlers/createHandler.js.map +1 -1
- package/lib/module/index.js +5 -7
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
- package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
- package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.js.map +1 -1
- package/lib/typescript/RNGestureHandlerModule.d.ts +2 -2
- package/lib/typescript/components/GestureHandlerRootView.d.ts +6 -6
- package/lib/typescript/handlers/createHandler.d.ts +11 -11
- package/lib/typescript/index.d.ts +47 -42
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +14 -14
- package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +14 -14
- package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +6 -6
- package/package.json +73 -72
- package/src/RNGestureHandlerModule.ts +4 -4
- package/src/components/GestureHandlerRootView.tsx +23 -23
- package/src/handlers/createHandler.tsx +534 -534
- package/src/index.ts +172 -172
- package/src/specs/NativeRNGestureHandlerModule.ts +26 -26
- package/src/specs/RNGestureHandlerButtonNativeComponent.ts +18 -18
- package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +6 -6
@@ -0,0 +1,106 @@
|
|
1
|
+
import { IncomingEvent } from './IncomingEvent';
|
2
|
+
import { CircularBuffer } from './CircularBuffer';
|
3
|
+
import { LeastSquareSolver } from './LeastSquareSolver';
|
4
|
+
|
5
|
+
export interface TrackerElement {
|
6
|
+
lastX: number;
|
7
|
+
lastY: number;
|
8
|
+
timeStamp: number;
|
9
|
+
velocityX: number;
|
10
|
+
velocityY: number;
|
11
|
+
}
|
12
|
+
|
13
|
+
export class VelocityTracker {
|
14
|
+
private assumePointerMoveStoppedMilliseconds = 40;
|
15
|
+
private historySize = 20;
|
16
|
+
private horizonMilliseconds = 300;
|
17
|
+
private minSampleSize = 3;
|
18
|
+
|
19
|
+
private samples: CircularBuffer<IncomingEvent>;
|
20
|
+
|
21
|
+
constructor() {
|
22
|
+
this.samples = new CircularBuffer<IncomingEvent>(this.historySize);
|
23
|
+
}
|
24
|
+
|
25
|
+
public add(event: IncomingEvent): void {
|
26
|
+
this.samples.push(event);
|
27
|
+
}
|
28
|
+
|
29
|
+
/// Returns an estimate of the velocity of the object being tracked by the
|
30
|
+
/// tracker given the current information available to the tracker.
|
31
|
+
///
|
32
|
+
/// Information is added using [addPosition].
|
33
|
+
///
|
34
|
+
/// Returns null if there is no data on which to base an estimate.
|
35
|
+
private getVelocityEstimate(): [number, number] | null {
|
36
|
+
const x = [];
|
37
|
+
const y = [];
|
38
|
+
const w = [];
|
39
|
+
const time = [];
|
40
|
+
|
41
|
+
let sampleCount = 0;
|
42
|
+
let index = this.samples.size - 1;
|
43
|
+
const newestSample = this.samples.get(index);
|
44
|
+
if (!newestSample) {
|
45
|
+
return null;
|
46
|
+
}
|
47
|
+
|
48
|
+
let previousSample = newestSample;
|
49
|
+
|
50
|
+
// Starting with the most recent PointAtTime sample, iterate backwards while
|
51
|
+
// the samples represent continuous motion.
|
52
|
+
while (sampleCount < this.samples.size) {
|
53
|
+
const sample = this.samples.get(index);
|
54
|
+
|
55
|
+
const age = newestSample.time - sample.time;
|
56
|
+
const delta = Math.abs(sample.time - previousSample.time);
|
57
|
+
previousSample = sample;
|
58
|
+
|
59
|
+
if (
|
60
|
+
age > this.horizonMilliseconds ||
|
61
|
+
delta > this.assumePointerMoveStoppedMilliseconds
|
62
|
+
) {
|
63
|
+
break;
|
64
|
+
}
|
65
|
+
|
66
|
+
x.push(sample.x);
|
67
|
+
y.push(sample.y);
|
68
|
+
w.push(1);
|
69
|
+
time.push(-age);
|
70
|
+
|
71
|
+
sampleCount++;
|
72
|
+
index--;
|
73
|
+
}
|
74
|
+
|
75
|
+
if (sampleCount >= this.minSampleSize) {
|
76
|
+
const xSolver = new LeastSquareSolver(time, x, w);
|
77
|
+
const xFit = xSolver.solve(2);
|
78
|
+
|
79
|
+
if (xFit !== null) {
|
80
|
+
const ySolver = new LeastSquareSolver(time, y, w);
|
81
|
+
const yFit = ySolver.solve(2);
|
82
|
+
|
83
|
+
if (yFit !== null) {
|
84
|
+
const xVelocity = xFit.coefficients[1] * 1000;
|
85
|
+
const yVelocity = yFit.coefficients[1] * 1000;
|
86
|
+
|
87
|
+
return [xVelocity, yVelocity];
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
return null;
|
93
|
+
}
|
94
|
+
|
95
|
+
public getVelocity(): [number, number] {
|
96
|
+
const estimate = this.getVelocityEstimate();
|
97
|
+
if (estimate !== null) {
|
98
|
+
return estimate;
|
99
|
+
}
|
100
|
+
return [0, 0];
|
101
|
+
}
|
102
|
+
|
103
|
+
public reset(): void {
|
104
|
+
this.samples.clear();
|
105
|
+
}
|
106
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
export type Tag = number
|
2
|
+
|
3
|
+
export type BoundingBox = {
|
4
|
+
x: number;
|
5
|
+
y: number;
|
6
|
+
width: number;
|
7
|
+
height: number;
|
8
|
+
};
|
9
|
+
|
10
|
+
export interface View {
|
11
|
+
getTag(): Tag
|
12
|
+
|
13
|
+
isPositionInBounds({x, y}: {
|
14
|
+
x: number;
|
15
|
+
y: number
|
16
|
+
}): boolean
|
17
|
+
|
18
|
+
getBoundingRect(): BoundingBox
|
19
|
+
|
20
|
+
hasButtonRole(): boolean
|
21
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
export * from "./OutgoingEventDispatcher"
|
2
|
+
export * from "./OutgoingEvent"
|
3
|
+
export * from "./RNGHLogger"
|
4
|
+
export * from "./View"
|
5
|
+
export * from "./Vector2D"
|
6
|
+
export * from "./GestureHandler"
|
7
|
+
export * from "./IncomingEvent"
|
8
|
+
export * from "./GestureHandlerOrchestrator"
|
9
|
+
export * from "./InteractionManager"
|
10
|
+
export * from "./PointerTracker"
|
11
|
+
export * from "./RNGHError"
|
12
|
+
export * from "./State"
|
13
|
+
export * from "./GestureHandlerRegistry"
|
14
|
+
export * from "./ViewFinder"
|
15
|
+
export * from "./ViewRegistry"
|
@@ -0,0 +1,169 @@
|
|
1
|
+
import { DEFAULT_TOUCH_SLOP, IncomingEvent, EventType, PointerTracker } from '../core';
|
2
|
+
|
3
|
+
export interface ScaleGestureListener {
|
4
|
+
onScaleBegin: (detector: ScaleGestureDetector) => boolean;
|
5
|
+
onScale: (detector: ScaleGestureDetector) => boolean;
|
6
|
+
onScaleEnd: (detector: ScaleGestureDetector) => void;
|
7
|
+
}
|
8
|
+
|
9
|
+
export default class ScaleGestureDetector implements ScaleGestureListener {
|
10
|
+
public onScaleBegin: (detector: ScaleGestureDetector) => boolean;
|
11
|
+
public onScale: (detector: ScaleGestureDetector) => boolean;
|
12
|
+
public onScaleEnd: (detector: ScaleGestureDetector) => void;
|
13
|
+
|
14
|
+
private focusX!: number;
|
15
|
+
private focusY!: number;
|
16
|
+
|
17
|
+
private currentSpan!: number;
|
18
|
+
private prevSpan!: number;
|
19
|
+
private initialSpan!: number;
|
20
|
+
|
21
|
+
private currentTime!: number;
|
22
|
+
private prevTime!: number;
|
23
|
+
|
24
|
+
private inProgress = false;
|
25
|
+
|
26
|
+
private spanSlop: number;
|
27
|
+
private minSpan: number;
|
28
|
+
|
29
|
+
public constructor(callbacks: ScaleGestureListener) {
|
30
|
+
this.onScaleBegin = callbacks.onScaleBegin;
|
31
|
+
this.onScale = callbacks.onScale;
|
32
|
+
this.onScaleEnd = callbacks.onScaleEnd;
|
33
|
+
|
34
|
+
this.spanSlop = DEFAULT_TOUCH_SLOP * 2;
|
35
|
+
this.minSpan = 0;
|
36
|
+
}
|
37
|
+
|
38
|
+
public onTouchEvent(event: IncomingEvent, tracker: PointerTracker): boolean {
|
39
|
+
this.currentTime = event.time;
|
40
|
+
|
41
|
+
const action: EventType = event.eventType;
|
42
|
+
const numOfPointers = tracker.getTrackedPointersCount();
|
43
|
+
|
44
|
+
const streamComplete: boolean =
|
45
|
+
action === EventType.UP ||
|
46
|
+
action === EventType.ADDITIONAL_POINTER_UP ||
|
47
|
+
action === EventType.CANCEL;
|
48
|
+
|
49
|
+
if (action === EventType.DOWN || streamComplete) {
|
50
|
+
if (this.inProgress) {
|
51
|
+
this.onScaleEnd(this);
|
52
|
+
this.inProgress = false;
|
53
|
+
this.initialSpan = 0;
|
54
|
+
}
|
55
|
+
|
56
|
+
if (streamComplete) {
|
57
|
+
return true;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
const configChanged: boolean =
|
62
|
+
action === EventType.DOWN ||
|
63
|
+
action === EventType.ADDITIONAL_POINTER_UP ||
|
64
|
+
action === EventType.ADDITIONAL_POINTER_DOWN;
|
65
|
+
|
66
|
+
const pointerUp = action === EventType.ADDITIONAL_POINTER_UP;
|
67
|
+
|
68
|
+
const ignoredPointer: number | undefined = pointerUp
|
69
|
+
? event.pointerId
|
70
|
+
: undefined;
|
71
|
+
|
72
|
+
//Determine focal point
|
73
|
+
|
74
|
+
const div: number = pointerUp ? numOfPointers - 1 : numOfPointers;
|
75
|
+
|
76
|
+
const sumX = tracker.getSumX(ignoredPointer);
|
77
|
+
const sumY = tracker.getSumY(ignoredPointer);
|
78
|
+
|
79
|
+
const focusX = sumX / div;
|
80
|
+
const focusY = sumY / div;
|
81
|
+
|
82
|
+
//Determine average deviation from focal point
|
83
|
+
|
84
|
+
let devSumX = 0;
|
85
|
+
let devSumY = 0;
|
86
|
+
|
87
|
+
tracker.getData().forEach((value, key) => {
|
88
|
+
if (key === ignoredPointer) {
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
|
92
|
+
devSumX += Math.abs(value.lastX - focusX);
|
93
|
+
devSumY += Math.abs(value.lastY - focusY);
|
94
|
+
});
|
95
|
+
|
96
|
+
const devX: number = devSumX / div;
|
97
|
+
const devY: number = devSumY / div;
|
98
|
+
|
99
|
+
const spanX: number = devX * 2;
|
100
|
+
const spanY: number = devY * 2;
|
101
|
+
|
102
|
+
const span = Math.hypot(spanX, spanY);
|
103
|
+
|
104
|
+
//Begin/end events
|
105
|
+
const wasInProgress: boolean = this.inProgress;
|
106
|
+
this.focusX = focusX;
|
107
|
+
this.focusY = focusY;
|
108
|
+
|
109
|
+
if (this.inProgress && (span < this.minSpan || configChanged)) {
|
110
|
+
this.onScaleEnd(this);
|
111
|
+
this.inProgress = false;
|
112
|
+
this.initialSpan = span;
|
113
|
+
}
|
114
|
+
|
115
|
+
if (configChanged) {
|
116
|
+
this.initialSpan = this.prevSpan = this.currentSpan = span;
|
117
|
+
}
|
118
|
+
|
119
|
+
if (
|
120
|
+
!this.inProgress &&
|
121
|
+
span >= this.minSpan &&
|
122
|
+
(wasInProgress || Math.abs(span - this.initialSpan) > this.spanSlop)
|
123
|
+
) {
|
124
|
+
this.prevSpan = this.currentSpan = span;
|
125
|
+
this.prevTime = this.currentTime;
|
126
|
+
this.inProgress = this.onScaleBegin(this);
|
127
|
+
}
|
128
|
+
|
129
|
+
//Handle motion
|
130
|
+
if (action !== EventType.MOVE) {
|
131
|
+
return true;
|
132
|
+
}
|
133
|
+
|
134
|
+
this.currentSpan = span;
|
135
|
+
|
136
|
+
if (this.inProgress && !this.onScale(this)) {
|
137
|
+
return true;
|
138
|
+
}
|
139
|
+
|
140
|
+
this.prevSpan = this.currentSpan;
|
141
|
+
this.prevTime = this.currentTime;
|
142
|
+
|
143
|
+
return true;
|
144
|
+
}
|
145
|
+
|
146
|
+
public getCurrentSpan(): number {
|
147
|
+
return this.currentSpan;
|
148
|
+
}
|
149
|
+
|
150
|
+
public getFocusX(): number {
|
151
|
+
return this.focusX;
|
152
|
+
}
|
153
|
+
|
154
|
+
public getFocusY(): number {
|
155
|
+
return this.focusY;
|
156
|
+
}
|
157
|
+
|
158
|
+
public getTimeDelta(): number {
|
159
|
+
return this.currentTime - this.prevTime;
|
160
|
+
}
|
161
|
+
|
162
|
+
public getScaleFactor(numOfPointers: number): number {
|
163
|
+
if (numOfPointers < 2) {
|
164
|
+
return 1;
|
165
|
+
}
|
166
|
+
|
167
|
+
return this.prevSpan > 0 ? this.currentSpan / this.prevSpan : 1;
|
168
|
+
}
|
169
|
+
}
|
@@ -0,0 +1,211 @@
|
|
1
|
+
import {
|
2
|
+
GestureHandler,
|
3
|
+
State,
|
4
|
+
DiagonalDirections,
|
5
|
+
Directions,
|
6
|
+
Vector2D,
|
7
|
+
IncomingEvent,
|
8
|
+
GestureHandlerDependencies
|
9
|
+
} from '../core';
|
10
|
+
|
11
|
+
const DEFAULT_MAX_DURATION_MS = 800;
|
12
|
+
const DEFAULT_MIN_VELOCITY = 700;
|
13
|
+
/**
|
14
|
+
* DEFAULT_ALIGNMENT_CONE defines the angular tolerance for fling gestures in degrees.
|
15
|
+
* *
|
16
|
+
* *
|
17
|
+
* *
|
18
|
+
* *------------>
|
19
|
+
* *
|
20
|
+
* *
|
21
|
+
* *
|
22
|
+
*/
|
23
|
+
const DEFAULT_ALIGNMENT_CONE = 30;
|
24
|
+
const DEFAULT_DIRECTION: Directions = Directions.RIGHT;
|
25
|
+
const DEFAULT_NUMBER_OF_TOUCHES_REQUIRED = 1;
|
26
|
+
const AXIAL_DEVIATION_COSINE = coneToDeviation(DEFAULT_ALIGNMENT_CONE);
|
27
|
+
const DIAGONAL_DEVIATION_COSINE = coneToDeviation(90 - DEFAULT_ALIGNMENT_CONE);
|
28
|
+
|
29
|
+
export class FlingGestureHandler extends GestureHandler {
|
30
|
+
constructor(deps: GestureHandlerDependencies) {
|
31
|
+
super({ ...deps, logger: deps.logger.cloneWithPrefix("FlingGestureHandler") })
|
32
|
+
}
|
33
|
+
|
34
|
+
getDefaultConfig() {
|
35
|
+
return {}
|
36
|
+
}
|
37
|
+
|
38
|
+
private get direction(): Directions {
|
39
|
+
return this.config.direction ?? DEFAULT_DIRECTION
|
40
|
+
}
|
41
|
+
|
42
|
+
private get numberOfPointersRequired() {
|
43
|
+
return this.config.numberOfPointers ?? DEFAULT_NUMBER_OF_TOUCHES_REQUIRED
|
44
|
+
}
|
45
|
+
|
46
|
+
private get maxDurationMs() {
|
47
|
+
return this.config.maxDurationMs ?? DEFAULT_MAX_DURATION_MS
|
48
|
+
}
|
49
|
+
|
50
|
+
private get minVelocity() {
|
51
|
+
return this.config.minVelocity ?? DEFAULT_MIN_VELOCITY
|
52
|
+
}
|
53
|
+
|
54
|
+
private delayTimeout!: number;
|
55
|
+
private maxNumberOfPointersSimultaneously = 0;
|
56
|
+
private keyPointer = NaN;
|
57
|
+
|
58
|
+
private startFling(): void {
|
59
|
+
this.logger.info("startFling")
|
60
|
+
this.begin();
|
61
|
+
|
62
|
+
this.maxNumberOfPointersSimultaneously = 1;
|
63
|
+
|
64
|
+
this.delayTimeout = setTimeout(() => this.fail(), this.maxDurationMs);
|
65
|
+
}
|
66
|
+
|
67
|
+
private tryEndFling(): boolean {
|
68
|
+
const logger = this.logger.cloneWithPrefix("tryEndFling")
|
69
|
+
const velocityVector = this.tracker.getVelocity(this.keyPointer);
|
70
|
+
|
71
|
+
const getAlignment = (
|
72
|
+
direction: Directions | DiagonalDirections,
|
73
|
+
minimalAlignmentCosine: number
|
74
|
+
) => {
|
75
|
+
return (
|
76
|
+
(direction & this.direction) === direction &&
|
77
|
+
velocityVector.computeCosine(
|
78
|
+
Vector2D.fromDirection(direction),
|
79
|
+
) > minimalAlignmentCosine
|
80
|
+
);
|
81
|
+
};
|
82
|
+
|
83
|
+
const axialDirectionsList = Object.values(Directions);
|
84
|
+
const diagonalDirectionsList = Object.values(DiagonalDirections);
|
85
|
+
|
86
|
+
// list of alignments to all activated directions
|
87
|
+
const axialAlignmentList = axialDirectionsList.map((direction) =>
|
88
|
+
getAlignment(direction, AXIAL_DEVIATION_COSINE)
|
89
|
+
);
|
90
|
+
|
91
|
+
const diagonalAlignmentList = diagonalDirectionsList.map((direction) =>
|
92
|
+
getAlignment(direction, DIAGONAL_DEVIATION_COSINE)
|
93
|
+
);
|
94
|
+
|
95
|
+
const isAligned =
|
96
|
+
axialAlignmentList.some(Boolean) || diagonalAlignmentList.some(Boolean);
|
97
|
+
|
98
|
+
const isFast = velocityVector.magnitude > this.minVelocity;
|
99
|
+
|
100
|
+
if (
|
101
|
+
this.maxNumberOfPointersSimultaneously ===
|
102
|
+
this.numberOfPointersRequired &&
|
103
|
+
isAligned &&
|
104
|
+
isFast
|
105
|
+
) {
|
106
|
+
clearTimeout(this.delayTimeout);
|
107
|
+
this.activate();
|
108
|
+
|
109
|
+
return true;
|
110
|
+
}
|
111
|
+
|
112
|
+
return false;
|
113
|
+
}
|
114
|
+
|
115
|
+
private endFling() {
|
116
|
+
this.logger.info("endFling")
|
117
|
+
if (!this.tryEndFling()) {
|
118
|
+
this.fail();
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
public onPointerDown(event: IncomingEvent): void {
|
123
|
+
this.tracker.addToTracker(event);
|
124
|
+
this.keyPointer = event.pointerId;
|
125
|
+
|
126
|
+
super.onPointerDown(event);
|
127
|
+
this.newPointerAction();
|
128
|
+
}
|
129
|
+
|
130
|
+
public onAdditionalPointerAdd(event: IncomingEvent): void {
|
131
|
+
this.tracker.addToTracker(event);
|
132
|
+
super.onAdditionalPointerAdd(event);
|
133
|
+
this.newPointerAction();
|
134
|
+
}
|
135
|
+
|
136
|
+
private newPointerAction(): void {
|
137
|
+
if (this.currentState === State.UNDETERMINED) {
|
138
|
+
this.startFling();
|
139
|
+
}
|
140
|
+
|
141
|
+
if (this.currentState !== State.BEGAN) {
|
142
|
+
return;
|
143
|
+
}
|
144
|
+
|
145
|
+
this.tryEndFling();
|
146
|
+
|
147
|
+
if (
|
148
|
+
this.tracker.getTrackedPointersCount() >
|
149
|
+
this.maxNumberOfPointersSimultaneously
|
150
|
+
) {
|
151
|
+
this.maxNumberOfPointersSimultaneously =
|
152
|
+
this.tracker.getTrackedPointersCount();
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
private pointerMoveAction(event: IncomingEvent): void {
|
157
|
+
this.logger.cloneWithPrefix("pointerMoveAction").info(JSON.stringify(event))
|
158
|
+
this.tracker.track(event);
|
159
|
+
|
160
|
+
if (this.currentState !== State.BEGAN) {
|
161
|
+
return;
|
162
|
+
}
|
163
|
+
|
164
|
+
this.tryEndFling();
|
165
|
+
}
|
166
|
+
|
167
|
+
public onPointerMove(event: IncomingEvent): void {
|
168
|
+
this.pointerMoveAction(event);
|
169
|
+
super.onPointerMove(event);
|
170
|
+
}
|
171
|
+
|
172
|
+
public onPointerOutOfBounds(event: IncomingEvent): void {
|
173
|
+
this.pointerMoveAction(event);
|
174
|
+
super.onPointerOutOfBounds(event);
|
175
|
+
}
|
176
|
+
|
177
|
+
public onPointerUp(event: IncomingEvent): void {
|
178
|
+
super.onPointerUp(event);
|
179
|
+
this.onUp(event);
|
180
|
+
|
181
|
+
this.keyPointer = NaN;
|
182
|
+
}
|
183
|
+
|
184
|
+
public onAdditionalPointerRemove(event: IncomingEvent): void {
|
185
|
+
super.onAdditionalPointerRemove(event);
|
186
|
+
this.onUp(event);
|
187
|
+
}
|
188
|
+
|
189
|
+
private onUp(event: IncomingEvent): void {
|
190
|
+
const logger = this.logger.cloneWithPrefix("onUp")
|
191
|
+
logger.info("start")
|
192
|
+
if (this.currentState === State.BEGAN) {
|
193
|
+
this.endFling();
|
194
|
+
}
|
195
|
+
logger.info(`removeFromTracker: pointerId=${event.pointerId}`)
|
196
|
+
this.tracker.removeFromTracker(event.pointerId);
|
197
|
+
}
|
198
|
+
|
199
|
+
public activate(): void {
|
200
|
+
super.activate();
|
201
|
+
this.end();
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
function coneToDeviation(degrees: number) {
|
206
|
+
return Math.cos(degToRad(degrees / 2));
|
207
|
+
}
|
208
|
+
|
209
|
+
function degToRad(degrees: number) {
|
210
|
+
return (degrees * Math.PI) / 180;
|
211
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import {
|
2
|
+
RNGHLogger,
|
3
|
+
InteractionManager,
|
4
|
+
RNGHError,
|
5
|
+
PointerTracker,
|
6
|
+
GestureHandler,
|
7
|
+
GestureHandlerDependencies,
|
8
|
+
ScrollLocker,
|
9
|
+
GestureHandlerOrchestrator,
|
10
|
+
RNGestureResponder
|
11
|
+
} from "../core"
|
12
|
+
import { TapGestureHandler } from './TapGestureHandler';
|
13
|
+
import { PanGestureHandler } from "./PanGestureHandler"
|
14
|
+
import { PinchGestureHandler } from "./PinchGestureHandler"
|
15
|
+
import { NativeViewGestureHandler } from "./NativeViewGestureHandler"
|
16
|
+
import { ManualGestureHandler } from './ManualGestureHandler';
|
17
|
+
import { LongPressGestureHandler } from "./LongPressGestureHandler"
|
18
|
+
import { FlingGestureHandler } from "./FlingGestureHandler"
|
19
|
+
import { RotationGestureHandler } from "./RotationGestureHandler"
|
20
|
+
|
21
|
+
export class GestureHandlerFactory {
|
22
|
+
private orchestrator: GestureHandlerOrchestrator
|
23
|
+
private logger: RNGHLogger
|
24
|
+
|
25
|
+
constructor(private cleanLogger: RNGHLogger, private scrollLocker: ScrollLocker, private interactionManager: InteractionManager, private rnGestureResponder: RNGestureResponder) {
|
26
|
+
this.logger = cleanLogger.cloneWithPrefix("Factory")
|
27
|
+
this.orchestrator = new GestureHandlerOrchestrator(cleanLogger.cloneWithPrefix("Orchestrator"))
|
28
|
+
}
|
29
|
+
|
30
|
+
create(handlerName: string, handlerTag: number): GestureHandler {
|
31
|
+
this.logger.info(`create ${handlerName} with handlerTag: ${handlerTag}`)
|
32
|
+
const deps: GestureHandlerDependencies = {
|
33
|
+
tracker: new PointerTracker(),
|
34
|
+
orchestrator: this.orchestrator,
|
35
|
+
handlerTag,
|
36
|
+
interactionManager: this.interactionManager,
|
37
|
+
logger: this.cleanLogger.cloneWithPrefix("GestureHandler"),
|
38
|
+
scrollLocker: this.scrollLocker,
|
39
|
+
rnGestureResponder: this.rnGestureResponder,
|
40
|
+
}
|
41
|
+
switch (handlerName) {
|
42
|
+
case "TapGestureHandler":
|
43
|
+
return new TapGestureHandler(deps)
|
44
|
+
case "PanGestureHandler":
|
45
|
+
return new PanGestureHandler(deps)
|
46
|
+
case "PinchGestureHandler":
|
47
|
+
return new PinchGestureHandler(deps)
|
48
|
+
case "NativeViewGestureHandler":
|
49
|
+
return new NativeViewGestureHandler(deps)
|
50
|
+
case "ManualGestureHandler":
|
51
|
+
return new ManualGestureHandler(deps)
|
52
|
+
case "LongPressGestureHandler":
|
53
|
+
return new LongPressGestureHandler(deps)
|
54
|
+
case "FlingGestureHandler":
|
55
|
+
return new FlingGestureHandler(deps)
|
56
|
+
case "RotationGestureHandler":
|
57
|
+
return new RotationGestureHandler(deps)
|
58
|
+
default:
|
59
|
+
const msg = `Unknown handler type: ${handlerName}`
|
60
|
+
this.logger.info(msg)
|
61
|
+
throw new RNGHError(msg)
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|