1 | import { supportsPassiveEventListener } from '@material/mwc-base/utils.js';
|
2 | function toPointer(ev) {
|
3 | const { clientX, clientY, pageX, pageY } = ev;
|
4 | const x = Math.max(pageX, clientX);
|
5 | const y = Math.max(pageY, clientY);
|
6 | const id = ev.identifier || ev.pointerId;
|
7 | return { x, y, id: id == null ? 0 : id };
|
8 | }
|
9 | function getFirstTouch(startPointer, ev) {
|
10 | const changedTouches = ev.changedTouches;
|
11 | if (changedTouches == null)
|
12 | return { newPointer: toPointer(ev), oldPointer: startPointer };
|
13 | const touches = Array.from(changedTouches, n => toPointer(n));
|
14 | const newPointer = startPointer == null
|
15 | ? touches[0]
|
16 | : touches.find(n => n.id === startPointer.id);
|
17 | return { newPointer, oldPointer: startPointer };
|
18 | }
|
19 | function addPassiveEventListener(node, event, callback) {
|
20 | node.addEventListener(event, callback, supportsPassiveEventListener ? { passive: true } : false);
|
21 | }
|
22 | export class Tracker {
|
23 | constructor(_element, handlers) {
|
24 | this._element = _element;
|
25 | this._startPointer = null;
|
26 | const { down, move, up } = handlers;
|
27 | this._down = this._onDown(down);
|
28 | this._move = this._onMove(move);
|
29 | this._up = this._onUp(up);
|
30 | if (_element && _element.addEventListener) {
|
31 | _element.addEventListener('mousedown', this._down);
|
32 | addPassiveEventListener(_element, 'touchstart', this._down);
|
33 | addPassiveEventListener(_element, 'touchmove', this._move);
|
34 | addPassiveEventListener(_element, 'touchend', this._up);
|
35 | }
|
36 | }
|
37 | disconnect() {
|
38 | const rootEl = this._element;
|
39 | if (rootEl && rootEl.removeEventListener) {
|
40 | rootEl.removeEventListener('mousedown', this._down);
|
41 | rootEl.removeEventListener('touchstart', this._down);
|
42 | rootEl.removeEventListener('touchmove', this._move);
|
43 | rootEl.removeEventListener('touchend', this._up);
|
44 | }
|
45 | }
|
46 | _onDown(down) {
|
47 | return (ev) => {
|
48 | if (ev instanceof MouseEvent) {
|
49 | this._element.addEventListener('mousemove', this._move);
|
50 | this._element.addEventListener('mouseup', this._up);
|
51 | this._element.addEventListener('mouseleave', this._up);
|
52 | }
|
53 | const { newPointer } = getFirstTouch(this._startPointer, ev);
|
54 | down(newPointer, ev);
|
55 | this._startPointer = newPointer;
|
56 | };
|
57 | }
|
58 | _onMove(move) {
|
59 | return (ev) => {
|
60 | this._updatePointers(move, ev);
|
61 | };
|
62 | }
|
63 | _onUp(up) {
|
64 | return (ev) => {
|
65 | this._updatePointers(up, ev, true);
|
66 | };
|
67 | }
|
68 | _updatePointers(cb, ev, shouldReset) {
|
69 | if (shouldReset && ev instanceof MouseEvent) {
|
70 | this._element.removeEventListener('mousemove', this._move);
|
71 | this._element.removeEventListener('mouseup', this._up);
|
72 | this._element.removeEventListener('mouseleave', this._up);
|
73 | }
|
74 | const { newPointer, oldPointer } = getFirstTouch(this._startPointer, ev);
|
75 | cb(newPointer, oldPointer, ev);
|
76 | this._startPointer = shouldReset ? null : newPointer;
|
77 | }
|
78 | }
|