@react-native-oh-tpl/react-native-gesture-handler 2.12.9 → 2.14.1-2.14.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. package/DrawerLayout/index.ts +2 -0
  2. package/Swipeable/index.ts +2 -0
  3. package/harmony/gesture_handler/BuildProfile.ets +15 -3
  4. package/harmony/gesture_handler/hvigorfile.ts +1 -1
  5. package/harmony/gesture_handler/index.ets +2 -2
  6. package/harmony/gesture_handler/oh-package-lock.json5 +4 -3
  7. package/harmony/gesture_handler/oh-package.json5 +3 -3
  8. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +64 -18
  9. package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +3 -3
  10. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewJSIBinder.h +2 -2
  11. package/harmony/gesture_handler/src/main/cpp/{RNGestureHandlerButtonComponentInstance.h → componentInstances/RNGestureHandlerButtonComponentInstance.h} +2 -2
  12. package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +242 -0
  13. package/harmony/gesture_handler/src/main/ets/{GestureHandler.ts → core/GestureHandler.ts} +54 -27
  14. package/harmony/gesture_handler/src/main/ets/{GestureHandlerOrchestrator.ts → core/GestureHandlerOrchestrator.ts} +122 -67
  15. package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +63 -0
  16. package/harmony/gesture_handler/src/main/ets/{Event.ts → core/IncomingEvent.ts} +30 -20
  17. package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +144 -0
  18. package/harmony/gesture_handler/src/main/ets/{OutgoingEvent.ts → core/OutgoingEvent.ts} +1 -1
  19. package/harmony/gesture_handler/src/main/ets/core/OutgoingEventDispatcher.ts +12 -0
  20. package/harmony/gesture_handler/src/main/ets/{PointerTracker.ts → core/PointerTracker.ts} +4 -4
  21. package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +12 -0
  22. package/harmony/gesture_handler/src/main/ets/core/Vector2D.ts +80 -0
  23. package/harmony/gesture_handler/src/main/ets/{VelocityTracker.ts → core/VelocityTracker.ts} +13 -5
  24. package/harmony/gesture_handler/src/main/ets/core/View.ts +21 -0
  25. package/harmony/gesture_handler/src/main/ets/core/ViewFinder.ts +11 -0
  26. package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +8 -0
  27. package/harmony/gesture_handler/src/main/ets/core/index.ts +15 -0
  28. package/harmony/gesture_handler/src/main/ets/detectors/ScaleGestureDetector.ts +169 -0
  29. package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +211 -0
  30. package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +64 -0
  31. package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +127 -0
  32. package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +42 -0
  33. package/harmony/gesture_handler/src/main/ets/{NativeViewGestureHandler.ts → gesture-handlers/NativeViewGestureHandler.ts} +15 -15
  34. package/harmony/gesture_handler/src/main/ets/{PanGestureHandler.ts → gesture-handlers/PanGestureHandler.ts} +27 -13
  35. package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +159 -0
  36. package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +164 -0
  37. package/harmony/gesture_handler/src/main/ets/{TapGestureHandler.ts → gesture-handlers/TapGestureHandler.ts} +11 -11
  38. package/harmony/gesture_handler/src/main/ets/gesture-handlers/detectors/RotationGestureDetector.ts +167 -0
  39. package/harmony/gesture_handler/src/main/ets/gesture-handlers/index.ts +1 -0
  40. package/harmony/gesture_handler/src/main/ets/namespace/RNGestureHandlerModule.ts +8 -9
  41. package/harmony/gesture_handler/src/main/ets/namespace/{RNGestureHandlerButton.ts → components/RNGestureHandlerButton.ts} +35 -36
  42. package/harmony/gesture_handler/src/main/ets/namespace/{RNGestureHandlerRootView.ts → components/RNGestureHandlerRootView.ts} +23 -23
  43. package/harmony/gesture_handler/src/main/ets/namespace/components/ts.ts +2 -0
  44. package/harmony/gesture_handler/src/main/ets/namespace/ts.ts +2 -3
  45. package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerArkUIAdapter.ts +240 -0
  46. package/harmony/gesture_handler/src/main/ets/{GestureHandlerPackage.ts → rnoh/GestureHandlerPackage.ts} +4 -4
  47. package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +49 -0
  48. package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +71 -0
  49. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerArkTS.ts +98 -0
  50. package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +110 -0
  51. package/harmony/gesture_handler/src/main/ets/{RNGestureHandlerButton.ets → rnoh/RNGestureHandlerButton.ets} +3 -3
  52. package/harmony/gesture_handler/src/main/ets/{RNGestureHandlerModule.ts → rnoh/RNGestureHandlerModule.ts} +79 -29
  53. package/harmony/gesture_handler/src/main/ets/{RNGestureHandlerRootView.ets → rnoh/RNGestureHandlerRootView.ets} +3 -3
  54. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +24 -0
  55. package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +32 -0
  56. package/harmony/gesture_handler/src/main/ets/rnoh/View.ts +134 -0
  57. package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +97 -0
  58. package/harmony/gesture_handler/src/main/module.json5 +8 -6
  59. package/harmony/gesture_handler/ts.ts +2 -2
  60. package/harmony/gesture_handler.har +0 -0
  61. package/lib/commonjs/index.js +126 -141
  62. package/lib/commonjs/index.js.map +1 -1
  63. package/lib/module/index.js +13 -146
  64. package/lib/module/index.js.map +1 -1
  65. package/lib/typescript/index.d.ts +39 -1
  66. package/lib/typescript/index.d.ts.map +1 -1
  67. package/package.json +13 -10
  68. package/src/index.ts +140 -140
  69. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerPackage.h +0 -72
  70. package/harmony/gesture_handler/src/main/cpp/RNGestureHandlerRootViewComponentInstance.h +0 -78
  71. package/harmony/gesture_handler/src/main/ets/EventDispatcher.ts +0 -53
  72. package/harmony/gesture_handler/src/main/ets/GestureHandlerArkUIAdapter.ts +0 -203
  73. package/harmony/gesture_handler/src/main/ets/GestureHandlerFactory.ts +0 -45
  74. package/harmony/gesture_handler/src/main/ets/GestureHandlerRegistry.ts +0 -28
  75. package/harmony/gesture_handler/src/main/ets/InteractionManager.ts +0 -109
  76. package/harmony/gesture_handler/src/main/ets/RNGHLogger.ts +0 -48
  77. package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandlerArkTS.ts +0 -60
  78. package/harmony/gesture_handler/src/main/ets/RNGHRootTouchHandlerCAPI.ts +0 -87
  79. package/harmony/gesture_handler/src/main/ets/RNOHScrollLocker.ts +0 -23
  80. package/harmony/gesture_handler/src/main/ets/Vector2D.ts +0 -36
  81. package/harmony/gesture_handler/src/main/ets/View.ts +0 -71
  82. package/harmony/gesture_handler/src/main/ets/ViewRegistry.ts +0 -43
  83. package/harmony/gesture_handler/src/main/ets/pages/Index.ets +0 -17
  84. package/harmony/gesture_handler/src/main/ets/webviewability/WebviewAbility.ts +0 -41
  85. /package/harmony/gesture_handler/src/main/ets/{CircularBuffer.ts → core/CircularBuffer.ts} +0 -0
  86. /package/harmony/gesture_handler/src/main/ets/{LeastSquareSolver.ts → core/LeastSquareSolver.ts} +0 -0
  87. /package/harmony/gesture_handler/src/main/ets/{RNGHError.ts → core/RNGHError.ts} +0 -0
  88. /package/harmony/gesture_handler/src/main/ets/{State.ts → core/State.ts} +0 -0
  89. /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
+ }
@@ -1,5 +1,5 @@
1
1
  import { State } from "./State"
2
- import { TouchEventType } from "./Event"
2
+ import { TouchEventType } from "./IncomingEvent"
3
3
 
4
4
  export interface GestureEventPayload {
5
5
  handlerTag: number;
@@ -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 { TrackerElement, AdaptedEvent } from "./Event"
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: AdaptedEvent): void {
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: AdaptedEvent): void {
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,12 @@
1
+ export type RNGHLoggerMessage = string | Object
2
+
3
+ export interface RNGHLogger {
4
+ info(msg: string): void;
5
+
6
+ cloneWithPrefix(prefix: string): RNGHLogger;
7
+
8
+ debug(msg: RNGHLoggerMessage);
9
+
10
+ error(msg: string);
11
+ }
12
+
@@ -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 { AdaptedEvent } from './Event';
1
+ import { IncomingEvent } from './IncomingEvent';
2
2
  import { CircularBuffer } from './CircularBuffer';
3
3
  import { LeastSquareSolver } from './LeastSquareSolver';
4
4
 
5
- export default class VelocityTracker {
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<AdaptedEvent>;
19
+ private samples: CircularBuffer<IncomingEvent>;
12
20
 
13
21
  constructor() {
14
- this.samples = new CircularBuffer<AdaptedEvent>(this.historySize);
22
+ this.samples = new CircularBuffer<IncomingEvent>(this.historySize);
15
23
  }
16
24
 
17
- public add(event: AdaptedEvent): void {
25
+ public add(event: IncomingEvent): void {
18
26
  this.samples.push(event);
19
27
  }
20
28
 
@@ -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,11 @@
1
+ import { Tag, View } from "./View"
2
+
3
+ export interface ViewFinder {
4
+ getTouchableViewsAt(
5
+ pointRelativeToRoot: {
6
+ x: number,
7
+ y: number
8
+ },
9
+ rootTag: Tag
10
+ ): View[]
11
+ }
@@ -0,0 +1,8 @@
1
+ import { Tag, View } from "./View"
2
+ import { ViewFinder } from "./ViewFinder"
3
+
4
+ export interface ViewRegistry extends ViewFinder {
5
+ getViewByTag(viewTag: Tag): View | undefined
6
+ save(view: View): void
7
+ deleteByTag(viewTag: Tag): void
8
+ }
@@ -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
+ }