@react-native-oh-tpl/react-native-gesture-handler 2.12.9 → 2.14.1-2.14.9
Sign up to get free protection for your applications and to get access to all the features.
- package/DrawerLayout/index.ts +2 -0
- package/Swipeable/index.ts +2 -0
- package/harmony/gesture_handler/BuildProfile.ets +15 -3
- package/harmony/gesture_handler/hvigorfile.ts +1 -1
- package/harmony/gesture_handler/index.ets +2 -2
- package/harmony/gesture_handler/oh-package-lock.json5 +4 -3
- package/harmony/gesture_handler/oh-package.json5 +4 -4
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +63 -17
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +3 -3
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewJSIBinder.h +2 -2
- package/harmony/gesture_handler/src/main/cpp/{RNGestureHandlerButtonComponentInstance.h → componentInstances/RNGestureHandlerButtonComponentInstance.h} +2 -2
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +234 -0
- package/harmony/gesture_handler/src/main/ets/{GestureHandler.ts → core/GestureHandler.ts} +46 -25
- package/harmony/gesture_handler/src/main/ets/{GestureHandlerOrchestrator.ts → core/GestureHandlerOrchestrator.ts} +122 -67
- package/harmony/gesture_handler/src/main/ets/{GestureHandlerRegistry.ts → core/GestureHandlerRegistry.ts} +7 -0
- package/harmony/gesture_handler/src/main/ets/{Event.ts → core/IncomingEvent.ts} +30 -20
- package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
- package/harmony/gesture_handler/src/main/ets/{OutgoingEvent.ts → core/OutgoingEvent.ts} +1 -1
- package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
- package/harmony/gesture_handler/src/main/ets/{PointerTracker.ts → core/PointerTracker.ts} +4 -4
- package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +12 -0
- package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
- package/harmony/gesture_handler/src/main/ets/{VelocityTracker.ts → core/VelocityTracker.ts} +13 -5
- package/harmony/gesture_handler/src/main/ets/core/View.ts +19 -0
- package/harmony/gesture_handler/src/main/ets/core/index.ts +13 -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/{NativeViewGestureHandler.ts → gesture-handlers/NativeViewGestureHandler.ts} +10 -12
- package/harmony/gesture_handler/src/main/ets/{PanGestureHandler.ts → gesture-handlers/PanGestureHandler.ts} +27 -13
- 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/{TapGestureHandler.ts → gesture-handlers/TapGestureHandler.ts} +11 -11
- 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 +8 -9
- package/harmony/gesture_handler/src/main/ets/namespace/{RNGestureHandlerButton.ts → components/RNGestureHandlerButton.ts} +35 -36
- package/harmony/gesture_handler/src/main/ets/namespace/{RNGestureHandlerRootView.ts → components/RNGestureHandlerRootView.ts} +23 -23
- package/harmony/gesture_handler/src/main/ets/namespace/components/ts.ts +2 -0
- package/harmony/gesture_handler/src/main/ets/namespace/ts.ts +2 -3
- package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerArkUIAdapter.ts +240 -0
- package/harmony/gesture_handler/src/main/ets/{GestureHandlerPackage.ts → rnoh/GestureHandlerPackage.ts} +4 -4
- 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 +104 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +110 -0
- package/harmony/gesture_handler/src/main/ets/{RNGestureHandlerButton.ets → rnoh/RNGestureHandlerButton.ets} +3 -3
- package/harmony/gesture_handler/src/main/ets/{RNGestureHandlerModule.ts → rnoh/RNGestureHandlerModule.ts} +74 -27
- package/harmony/gesture_handler/src/main/ets/{RNGestureHandlerRootView.ets → rnoh/RNGestureHandlerRootView.ets} +3 -3
- 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 +119 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +95 -0
- package/harmony/gesture_handler/src/main/module.json5 +8 -6
- package/harmony/gesture_handler/ts.ts +2 -2
- package/harmony/gesture_handler.har +0 -0
- package/lib/commonjs/index.js +98 -138
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +9 -142
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +35 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +13 -10
- package/src/index.ts +136 -136
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerPackage.h +0 -72
- package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentInstance.h +0 -78
- package/harmony/gesture_handler/src/main/ets/EventDispatcher.ts +0 -53
- package/harmony/gesture_handler/src/main/ets/GestureHandlerArkUIAdapter.ts +0 -203
- package/harmony/gesture_handler/src/main/ets/GestureHandlerFactory.ts +0 -45
- package/harmony/gesture_handler/src/main/ets/InteractionManager.ts +0 -109
- package/harmony/gesture_handler/src/main/ets/RNGHLogger.ts +0 -48
- package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandlerArkTS.ts +0 -60
- package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandlerCAPI.ts +0 -87
- package/harmony/gesture_handler/src/main/ets/RNOHScrollLocker.ts +0 -23
- package/harmony/gesture_handler/src/main/ets/Vector2D.ts +0 -36
- package/harmony/gesture_handler/src/main/ets/View.ts +0 -71
- package/harmony/gesture_handler/src/main/ets/ViewRegistry.ts +0 -43
- package/harmony/gesture_handler/src/main/ets/pages/Index.ets +0 -17
- package/harmony/gesture_handler/src/main/ets/webviewability/WebviewAbility.ts +0 -41
- /package/harmony/gesture_handler/src/main/ets/{CircularBuffer.ts → core/CircularBuffer.ts} +0 -0
- /package/harmony/gesture_handler/src/main/ets/{LeastSquareSolver.ts → core/LeastSquareSolver.ts} +0 -0
- /package/harmony/gesture_handler/src/main/ets/{RNGHError.ts → core/RNGHError.ts} +0 -0
- /package/harmony/gesture_handler/src/main/ets/{State.ts → core/State.ts} +0 -0
- /package/harmony/gesture_handler/src/main/ets/{types.ts → rnoh/types.ts} +0 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
import { GestureHandler, Handler, GestureConfig as Config, GHTag } from "./GestureHandler"
|
2
|
+
import { RNGHLogger } from "./RNGHLogger"
|
3
|
+
|
4
|
+
export class InteractionManager {
|
5
|
+
private readonly waitForRelations: Map<GHTag, Set<GHTag>> = new Map()
|
6
|
+
private readonly simultaneousRelations: Map<GHTag, GHTag[]> = new Map()
|
7
|
+
private readonly blocksHandlersRelations: Map<GHTag, GHTag[]> = new Map();
|
8
|
+
|
9
|
+
private logger: RNGHLogger
|
10
|
+
|
11
|
+
constructor(logger: RNGHLogger) {
|
12
|
+
this.logger = logger.cloneWithPrefix("InteractionManager")
|
13
|
+
}
|
14
|
+
|
15
|
+
public configureInteractions(handler: GestureHandler, config: Config) {
|
16
|
+
this.dropRelationsForHandlerWithTag(handler.getTag());
|
17
|
+
|
18
|
+
if (config.waitFor) {
|
19
|
+
const waitFor = new Set<GHTag>();
|
20
|
+
config.waitFor.forEach((otherHandler: Handler): void => {
|
21
|
+
// New API reference
|
22
|
+
if (typeof otherHandler === 'number') {
|
23
|
+
waitFor.add(otherHandler);
|
24
|
+
} else {
|
25
|
+
// Old API reference
|
26
|
+
waitFor.add(otherHandler.handlerTag);
|
27
|
+
}
|
28
|
+
});
|
29
|
+
|
30
|
+
this.waitForRelations.set(handler.getTag(), waitFor);
|
31
|
+
}
|
32
|
+
|
33
|
+
if (config.simultaneousHandlers) {
|
34
|
+
const simultaneousHandlers: number[] = [];
|
35
|
+
config.simultaneousHandlers.forEach((otherHandler: Handler): void => {
|
36
|
+
if (typeof otherHandler === 'number') {
|
37
|
+
simultaneousHandlers.push(otherHandler);
|
38
|
+
} else {
|
39
|
+
simultaneousHandlers.push(otherHandler.handlerTag);
|
40
|
+
}
|
41
|
+
});
|
42
|
+
|
43
|
+
this.simultaneousRelations.set(handler.getTag(), simultaneousHandlers);
|
44
|
+
}
|
45
|
+
|
46
|
+
if (config.blocksHandlers) {
|
47
|
+
const blocksHandlers: number[] = [];
|
48
|
+
config.blocksHandlers.forEach((otherHandler: Handler): void => {
|
49
|
+
if (typeof otherHandler === 'number') {
|
50
|
+
blocksHandlers.push(otherHandler);
|
51
|
+
} else {
|
52
|
+
blocksHandlers.push(otherHandler.handlerTag);
|
53
|
+
}
|
54
|
+
});
|
55
|
+
this.blocksHandlersRelations.set(handler.getTag(), blocksHandlers);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
public shouldWaitForHandlerFailure(
|
60
|
+
handler: GestureHandler,
|
61
|
+
otherHandler: GestureHandler
|
62
|
+
): boolean {
|
63
|
+
const logger = this.logger.cloneWithPrefix(`shouldWaitForHandlerFailure(${handler.getTag()}, ${otherHandler.getTag()})`)
|
64
|
+
const waitFor = this.waitForRelations.get(
|
65
|
+
handler.getTag()
|
66
|
+
);
|
67
|
+
logger.debug({waitFor: Array.from(waitFor ?? [])})
|
68
|
+
if (!waitFor) {
|
69
|
+
logger.debug("false")
|
70
|
+
return false;
|
71
|
+
}
|
72
|
+
|
73
|
+
let shouldWait = false;
|
74
|
+
waitFor.forEach((tag: number): void => {
|
75
|
+
if (tag === otherHandler.getTag()) {
|
76
|
+
shouldWait = true;
|
77
|
+
return; //Returns from callback
|
78
|
+
}
|
79
|
+
});
|
80
|
+
logger.debug(shouldWait)
|
81
|
+
return shouldWait;
|
82
|
+
}
|
83
|
+
|
84
|
+
public shouldRecognizeSimultaneously(
|
85
|
+
handler: GestureHandler,
|
86
|
+
otherHandler: GestureHandler
|
87
|
+
): boolean {
|
88
|
+
const logger = this.logger.cloneWithPrefix(`shouldRecognizeSimultaneously(${handler.getTag()}, ${otherHandler.getTag()})`)
|
89
|
+
const simultaneousHandlers: number[] | undefined =
|
90
|
+
this.simultaneousRelations.get(handler.getTag());
|
91
|
+
if (!simultaneousHandlers) {
|
92
|
+
logger.debug(`false - Handler ${handler.getTag()} doesn't have simultaneousRelations specified`)
|
93
|
+
return false;
|
94
|
+
}
|
95
|
+
let shouldRecognizeSimultaneously = false;
|
96
|
+
simultaneousHandlers.forEach((tag: number): void => {
|
97
|
+
if (tag === otherHandler.getTag()) {
|
98
|
+
shouldRecognizeSimultaneously = true;
|
99
|
+
return;
|
100
|
+
}
|
101
|
+
});
|
102
|
+
logger.debug(`${shouldRecognizeSimultaneously} ${JSON.stringify({ simultaneousHandlers })}`)
|
103
|
+
return shouldRecognizeSimultaneously;
|
104
|
+
}
|
105
|
+
|
106
|
+
public shouldRequireHandlerToWaitForFailure(
|
107
|
+
handler: GestureHandler,
|
108
|
+
otherHandler: GestureHandler
|
109
|
+
): boolean {
|
110
|
+
const waitFor: number[] | undefined = this.blocksHandlersRelations.get(
|
111
|
+
handler.getTag()
|
112
|
+
);
|
113
|
+
|
114
|
+
return (
|
115
|
+
waitFor?.find((tag: number) => {
|
116
|
+
return tag === otherHandler.getTag();
|
117
|
+
}) !== undefined
|
118
|
+
);
|
119
|
+
}
|
120
|
+
|
121
|
+
public shouldHandlerBeCancelledBy(
|
122
|
+
handler: GestureHandler,
|
123
|
+
otherHandler: GestureHandler
|
124
|
+
): boolean {
|
125
|
+
const logger = this.logger.cloneWithPrefix(`shouldHandlerBeCancelledBy(handler=${handler.getTag()}, otherHandler=${otherHandler.getTag()})`)
|
126
|
+
// We check constructor name instead of using `instanceof` in order do avoid circular dependencies
|
127
|
+
// const isNativeHandler =
|
128
|
+
// otherHandler.constructor.name === 'NativeViewGestureHandler';
|
129
|
+
// const isActive = otherHandler.getState() === State.ACTIVE;
|
130
|
+
// const isButton = otherHandler.isButton?.() === true;
|
131
|
+
// return isNativeHandler && isActive && !isButton;
|
132
|
+
return false
|
133
|
+
}
|
134
|
+
|
135
|
+
public dropRelationsForHandlerWithTag(handlerTag: number): void {
|
136
|
+
this.waitForRelations.delete(handlerTag);
|
137
|
+
this.simultaneousRelations.delete(handlerTag);
|
138
|
+
}
|
139
|
+
|
140
|
+
public reset() {
|
141
|
+
this.waitForRelations.clear();
|
142
|
+
this.simultaneousRelations.clear();
|
143
|
+
}
|
144
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import {
|
2
|
+
GestureStateChangeEvent,
|
3
|
+
GestureUpdateEvent,
|
4
|
+
GestureTouchEvent,
|
5
|
+
} from './OutgoingEvent';
|
6
|
+
|
7
|
+
export interface OutgoingEventDispatcher {
|
8
|
+
onGestureHandlerStateChange(event: GestureStateChangeEvent): void;
|
9
|
+
onGestureHandlerEvent(
|
10
|
+
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
11
|
+
): void;
|
12
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import VelocityTracker from './VelocityTracker';
|
2
|
-
import {
|
1
|
+
import { VelocityTracker, TrackerElement } from './VelocityTracker';
|
2
|
+
import { IncomingEvent } from "./IncomingEvent"
|
3
3
|
import { Vector2D } from './Vector2D';
|
4
4
|
|
5
5
|
const MAX_POINTERS = 20;
|
@@ -25,7 +25,7 @@ export class PointerTracker {
|
|
25
25
|
}
|
26
26
|
}
|
27
27
|
|
28
|
-
public addToTracker(event:
|
28
|
+
public addToTracker(event: IncomingEvent): void {
|
29
29
|
if (this.trackedPointers.has(event.pointerId)) {
|
30
30
|
return;
|
31
31
|
}
|
@@ -54,7 +54,7 @@ export class PointerTracker {
|
|
54
54
|
this.removeMappedTouchId(pointerId);
|
55
55
|
}
|
56
56
|
|
57
|
-
public track(event:
|
57
|
+
public track(event: IncomingEvent): void {
|
58
58
|
const element: TrackerElement = this.trackedPointers.get(
|
59
59
|
event.pointerId
|
60
60
|
) as TrackerElement;
|
@@ -0,0 +1,80 @@
|
|
1
|
+
import { Directions, DiagonalDirections } from "./IncomingEvent"
|
2
|
+
|
3
|
+
type Cosine = number
|
4
|
+
|
5
|
+
export class Vector2D {
|
6
|
+
private static VECTOR_BY_DIRECTION = new Map<
|
7
|
+
Directions | DiagonalDirections,
|
8
|
+
Vector2D
|
9
|
+
>([
|
10
|
+
[Directions.LEFT, new Vector2D({ x: -1, y: 0 })],
|
11
|
+
[Directions.RIGHT, new Vector2D({ x: 1, y: 0 })],
|
12
|
+
[Directions.UP, new Vector2D({ x: 0, y: -1 })],
|
13
|
+
[Directions.DOWN, new Vector2D({ x: 0, y: 1 })],
|
14
|
+
[DiagonalDirections.UP_RIGHT, new Vector2D({ x: 1, y: -1 })],
|
15
|
+
[DiagonalDirections.DOWN_RIGHT, new Vector2D({ x: 1, y: 1 })],
|
16
|
+
[DiagonalDirections.UP_LEFT, new Vector2D({ x: -1, y: -1 })],
|
17
|
+
[DiagonalDirections.DOWN_LEFT, new Vector2D({ x: -1, y: 1 })],
|
18
|
+
]);
|
19
|
+
|
20
|
+
static fromDirection(direction: Directions | DiagonalDirections): Vector2D {
|
21
|
+
return Vector2D.VECTOR_BY_DIRECTION.get(direction)!;
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
constructor(
|
26
|
+
private val: {
|
27
|
+
x: number;
|
28
|
+
y: number;
|
29
|
+
} = {x: 0, y: 0},
|
30
|
+
) {}
|
31
|
+
|
32
|
+
get x() {
|
33
|
+
return this.val.x;
|
34
|
+
}
|
35
|
+
|
36
|
+
get y() {
|
37
|
+
return this.val.y;
|
38
|
+
}
|
39
|
+
|
40
|
+
get value() {
|
41
|
+
return {...this.val};
|
42
|
+
}
|
43
|
+
|
44
|
+
public clone() {
|
45
|
+
return new Vector2D({...this.val});
|
46
|
+
}
|
47
|
+
|
48
|
+
public subtract(vec: Vector2D) {
|
49
|
+
this.val.x -= vec.x;
|
50
|
+
this.val.y -= vec.y;
|
51
|
+
return this;
|
52
|
+
}
|
53
|
+
|
54
|
+
public add(vec: Vector2D) {
|
55
|
+
this.val.x += vec.x;
|
56
|
+
this.val.y += vec.y;
|
57
|
+
return this;
|
58
|
+
}
|
59
|
+
|
60
|
+
public createUnitVector(): Vector2D {
|
61
|
+
const magnitude = this.magnitude
|
62
|
+
if (magnitude === 0) {
|
63
|
+
return new Vector2D({ x: 0, y: 0 });
|
64
|
+
}
|
65
|
+
return new Vector2D({
|
66
|
+
x: this.val.x / magnitude,
|
67
|
+
y: this.val.y / magnitude
|
68
|
+
});
|
69
|
+
}
|
70
|
+
|
71
|
+
public computeCosine(other: Vector2D): Cosine {
|
72
|
+
const thisUnit = this.createUnitVector();
|
73
|
+
const otherUnit = other.createUnitVector();
|
74
|
+
return thisUnit.val.x * otherUnit.val.x + thisUnit.val.y * otherUnit.val.y;
|
75
|
+
}
|
76
|
+
|
77
|
+
public get magnitude() {
|
78
|
+
return Math.hypot(this.x, this.y);
|
79
|
+
}
|
80
|
+
}
|
@@ -1,20 +1,28 @@
|
|
1
|
-
import {
|
1
|
+
import { IncomingEvent } from './IncomingEvent';
|
2
2
|
import { CircularBuffer } from './CircularBuffer';
|
3
3
|
import { LeastSquareSolver } from './LeastSquareSolver';
|
4
4
|
|
5
|
-
export
|
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 {
|
6
14
|
private assumePointerMoveStoppedMilliseconds = 40;
|
7
15
|
private historySize = 20;
|
8
16
|
private horizonMilliseconds = 300;
|
9
17
|
private minSampleSize = 3;
|
10
18
|
|
11
|
-
private samples: CircularBuffer<
|
19
|
+
private samples: CircularBuffer<IncomingEvent>;
|
12
20
|
|
13
21
|
constructor() {
|
14
|
-
this.samples = new CircularBuffer<
|
22
|
+
this.samples = new CircularBuffer<IncomingEvent>(this.historySize);
|
15
23
|
}
|
16
24
|
|
17
|
-
public add(event:
|
25
|
+
public add(event: IncomingEvent): void {
|
18
26
|
this.samples.push(event);
|
19
27
|
}
|
20
28
|
|
@@ -0,0 +1,19 @@
|
|
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
|
+
}
|
@@ -0,0 +1,13 @@
|
|
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"
|
@@ -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
|
+
}
|