import getComputedTransformMatrix from './utils.js';
const minDistanceThreshold = 5;
function mainButtonPressed(e) {
return e.button === 0;
}
function distanceBetween({ x: x1, y: y1 }, { x: x2, y: y2 }) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
function exceedsMinDistanceThreshhold(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);
}
function getTransformMatrices(el) {
return {
computed: getComputedTransformMatrix(el),
inverseScreen: el.getScreenCTM().inverse()
};
}
function clientToSvgPt({ clientX, clientY }, { inverseScreen }, pt = new DOMPoint()) {
pt.x = clientX;
pt.y = clientY;
return pt.matrixTransform(inverseScreen);
}
function setPanTransform(el, { computed }, startPt, endPt) {
el.style.transform = computed.multiply(getTranslateMatrix(startPt, endPt));
}
export function programmaticPan(el, from, to) {
const matrices = getTransformMatrices(el);
const startPt = clientToSvgPt(from, matrices);
const endPt = clientToSvgPt(to, matrices);
el.style.transition = 'transform 0.5s';
setPanTransform(el, matrices, startPt, endPt);
el.addEventListener('transitionend', () => el.style.transition = '', { once: true });
}
export default function (el) {
let matrices, startPt, movePt, isPanning;
function pointerMove(e) {
movePt.x = e.clientX;
movePt.y = e.clientY;
if (!isPanning && exceedsMinDistanceThreshhold(startPt, movePt)) {
isPanning = true;
startPt = clientToSvgPt(e, matrices, startPt);
stopEventPropagationToChildren(el, 'click');
}
if (isPanning) {
movePt = clientToSvgPt(e, matrices, movePt);
setPanTransform(el, matrices, startPt, movePt);
}
}
return function(e) {
if (!mainButtonPressed(e)) return;
e.preventDefault();
e.target.setPointerCapture(e.pointerId);
isPanning = false;
matrices = getTransformMatrices(el);
startPt = new DOMPoint(e.clientX, e.clientY);
movePt = new DOMPoint();
this.addEventListener('pointermove', pointerMove);
this.addEventListener(
'pointerup',
() => this.removeEventListener('pointermove', pointerMove),
{ once: true }
);
}
}