|
@@ -27,7 +27,7 @@ import { TrackablePointer, TrackablePointerPhase } from './trackable-pointer';
|
27
|
27
|
import { PointerSource } from '../../sources/pointer-source';
|
28
|
28
|
import { Vector2 } from '../../geometry/vector2';
|
29
|
29
|
import { Utils, Nullable } from '../../utils/utils';
|
30
|
|
-import { IllegalOperationError } from '../../utils/errors';
|
|
30
|
+import { IllegalOperationError, IllegalArgumentError } from '../../utils/errors';
|
31
|
31
|
import { Session } from '../../core/session';
|
32
|
32
|
import { Viewport } from '../../core/viewport';
|
33
|
33
|
|
|
@@ -52,6 +52,38 @@ export interface PointerTrackerOutput extends TrackerOutput
|
52
|
52
|
readonly exports: PointerTrackerResult;
|
53
|
53
|
}
|
54
|
54
|
|
|
55
|
+/**
|
|
56
|
+ * The space in which pointers are located.
|
|
57
|
+ *
|
|
58
|
+ * - In "normalized" space, pointers are located in [-1,1]x[-1,1]. The origin
|
|
59
|
+ * of the space is at the center of the viewport. The x-axis points to the
|
|
60
|
+ * right and the y-axis points up. This is the default space.
|
|
61
|
+ *
|
|
62
|
+ * - The "adjusted" space is similar to the normalized space, except that it is
|
|
63
|
+ * scaled so that it matches the aspect ratio of the viewport.
|
|
64
|
+ *
|
|
65
|
+ * Pointers in adjusted space are contained in normalized space, but unless
|
|
66
|
+ * the viewport is a square, one of their coordinates, x or y, will no longer
|
|
67
|
+ * range from -1 to +1. It will range from -s to +s, where s = min(a, 1/a).
|
|
68
|
+ * In this expression, a is the aspect ratio of the viewport and s is less
|
|
69
|
+ * than or equal to 1.
|
|
70
|
+ *
|
|
71
|
+ * Selecting the adjusted space is useful for making sure that pointer speeds
|
|
72
|
+ * are equivalent in both axes and for preserving movement curves. Speeds are
|
|
73
|
+ * not equivalent and movement curves are not preserved by default because
|
|
74
|
+ * the normalized space is a square, whereas the viewport is a rectangle.
|
|
75
|
+ */
|
|
76
|
+export type PointerSpace = 'normalized' | 'adjusted'; // | 'viewport';
|
|
77
|
+
|
|
78
|
+/**
|
|
79
|
+ * Options for instantiating a PointerTracker
|
|
80
|
+ */
|
|
81
|
+export interface PointerTrackerOptions
|
|
82
|
+{
|
|
83
|
+ /** the space in which pointers will be located */
|
|
84
|
+ space?: PointerSpace;
|
|
85
|
+}
|
|
86
|
+
|
55
|
87
|
/** Convert event type to trackable pointer phase */
|
56
|
88
|
const EVENTTYPE2PHASE: Record<string, TrackablePointerPhase> = {
|
57
|
89
|
'pointerdown': 'began',
|
|
@@ -62,6 +94,11 @@ const EVENTTYPE2PHASE: Record<string, TrackablePointerPhase> = {
|
62
|
94
|
'pointerenter': 'began',
|
63
|
95
|
};
|
64
|
96
|
|
|
97
|
+/** Default options for instantiating a PointerTracker */
|
|
98
|
+const DEFAULT_OPTIONS: Readonly<Required<PointerTrackerOptions>> = {
|
|
99
|
+ space: 'normalized'
|
|
100
|
+};
|
|
101
|
+
|
65
|
102
|
|
66
|
103
|
|
67
|
104
|
|
|
@@ -76,6 +113,9 @@ export class PointerTracker implements Tracker
|
76
|
113
|
/** the viewport */
|
77
|
114
|
private _viewport: Nullable<Viewport>;
|
78
|
115
|
|
|
116
|
+ /** pointer space */
|
|
117
|
+ private _space: PointerSpace;
|
|
118
|
+
|
79
|
119
|
/** active pointers */
|
80
|
120
|
private _activePointers: Map<number, TrackablePointer>;
|
81
|
121
|
|
|
@@ -99,13 +139,20 @@ export class PointerTracker implements Tracker
|
99
|
139
|
|
100
|
140
|
|
101
|
141
|
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
102
|
145
|
/**
|
103
|
146
|
* Constructor
|
|
147
|
+ * @param options
|
104
|
148
|
*/
|
105
|
|
- constructor()
|
|
149
|
+ constructor(options: PointerTrackerOptions)
|
106
|
150
|
{
|
|
151
|
+ const settings = this._buildSettings(options);
|
|
152
|
+
|
107
|
153
|
this._source = null;
|
108
|
154
|
this._viewport = null;
|
|
155
|
+ this._space = settings.space;
|
109
|
156
|
this._activePointers = new Map();
|
110
|
157
|
this._newPointers = new Map();
|
111
|
158
|
this._idMap = new Map();
|
|
@@ -117,6 +164,21 @@ export class PointerTracker implements Tracker
|
117
|
164
|
}
|
118
|
165
|
|
119
|
166
|
/**
|
|
167
|
+ * Build a full and validated options object
|
|
168
|
+ * @param options
|
|
169
|
+ * @returns validated options with defaults
|
|
170
|
+ */
|
|
171
|
+ private _buildSettings(options: PointerTrackerOptions): Required<PointerTrackerOptions>
|
|
172
|
+ {
|
|
173
|
+ const settings: Required<PointerTrackerOptions> = Object.assign({}, DEFAULT_OPTIONS, options);
|
|
174
|
+
|
|
175
|
+ if(settings.space != 'normalized' && settings.space != 'adjusted')
|
|
176
|
+ throw new IllegalArgumentError(`Invalid pointer space: "${settings.space}"`);
|
|
177
|
+
|
|
178
|
+ return settings;
|
|
179
|
+ }
|
|
180
|
+
|
|
181
|
+ /**
|
120
|
182
|
* The type of the tracker
|
121
|
183
|
*/
|
122
|
184
|
get type(): string
|
|
@@ -283,13 +345,27 @@ export class PointerTracker implements Tracker
|
283
|
345
|
continue;
|
284
|
346
|
}
|
285
|
347
|
|
286
|
|
- // determine the current position
|
|
348
|
+ // determine the current position in normalized space
|
287
|
349
|
const absX = event.pageX - (rect.left + window.scrollX);
|
288
|
350
|
const absY = event.pageY - (rect.top + window.scrollY);
|
289
|
351
|
const relX = 2 * absX / rect.width - 1; // convert to [-1,1]
|
290
|
352
|
const relY = -(2 * absY / rect.height - 1); // flip Y axis
|
291
|
353
|
const position = new Vector2(relX, relY);
|
292
|
354
|
|
|
355
|
+ // scale the normalized space so that it matches the aspect ratio of the viewport
|
|
356
|
+ if(this._space == 'adjusted') {
|
|
357
|
+ const a = this._viewport!.aspectRatio;
|
|
358
|
+
|
|
359
|
+ if(a >= 1) {
|
|
360
|
+ // landscape
|
|
361
|
+ position._set(relX, relY / a);
|
|
362
|
+ }
|
|
363
|
+ else {
|
|
364
|
+ // portrait
|
|
365
|
+ position._set(relX * a, relY);
|
|
366
|
+ }
|
|
367
|
+ }
|
|
368
|
+
|
293
|
369
|
// determine the position delta
|
294
|
370
|
const deltaPosition = !previous ? Vector2.ZERO :
|
295
|
371
|
position._clone()._subtract(previous.position);
|
|
@@ -360,6 +436,15 @@ export class PointerTracker implements Tracker
|
360
|
436
|
}
|
361
|
437
|
|
362
|
438
|
/**
|
|
439
|
+ * The space in which pointers are located.
|
|
440
|
+ * You may set it when instantiating the tracker.
|
|
441
|
+ */
|
|
442
|
+ get space(): PointerSpace
|
|
443
|
+ {
|
|
444
|
+ return this._space;
|
|
445
|
+ }
|
|
446
|
+
|
|
447
|
+ /**
|
363
|
448
|
* Generate tracker output
|
364
|
449
|
* @returns a new PointerTrackerOutput object
|
365
|
450
|
*/
|