1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import getComputedTransformMatrix from './utils.js';
const minDistanceThreshold = 5;
function setToCurrentPointerCoords(point, e) {
point.x = e.clientX;
point.y = e.clientY;
return point;
}
function distanceBetween({ x: x1, y: y1 }, { x: x2, y: y2 }) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
function minDistanceThresholdIsMet(startPt, endPt) {
return distanceBetween(startPt, endPt) >= minDistanceThreshold;
}
function stopEventPropagationToChildren(el, type) {
el.addEventListener(type, e => e.stopPropagation(), { capture: true, once: true });
}
function getTranslateMatrix(startPt, movePt) {
const translateMatrix = new DOMMatrix();
return translateMatrix.translate(movePt.x - startPt.x, movePt.y - startPt.y);
}
export default function (el, e) {
e.preventDefault();
const mtx = getComputedTransformMatrix(el),
startPt = new DOMPoint(e.clientX, e.clientY),
movePt = new DOMPoint();
let isPanning = false;
function pointerMove(e) {
setToCurrentPointerCoords(movePt, e);
if (!isPanning && minDistanceThresholdIsMet(startPt, movePt)) {
isPanning = true;
e.target.setPointerCapture(e.pointerId);
setToCurrentPointerCoords(startPt, e);
stopEventPropagationToChildren(el, 'click');
}
if (isPanning) {
el.style.transform = getTranslateMatrix(startPt, movePt).multiply(mtx);
}
}
el.addEventListener('pointermove', pointerMove);
el.addEventListener(
'pointerup',
() => el.removeEventListener('pointermove', pointerMove),
{ once: true }
);
}
|