the-finger
Version:
JavaScript library to detect touch gestures: tap, double tap, press, long press, drag, flick, rotate, pinch, spread, pan, two-finger.
456 lines (455 loc) • 17.5 kB
JavaScript
var gt = Object.defineProperty;
var et = (g) => {
throw TypeError(g);
};
var pt = (g, s, i) => s in g ? gt(g, s, { enumerable: !0, configurable: !0, writable: !0, value: i }) : g[s] = i;
var nt = (g, s, i) => pt(g, typeof s != "symbol" ? s + "" : s, i), $ = (g, s, i) => s.has(g) || et("Cannot " + i);
var t = (g, s, i) => ($(g, s, "read from private field"), i ? i.call(g) : s.get(g)), f = (g, s, i) => s.has(g) ? et("Cannot add the same private member more than once") : s instanceof WeakSet ? s.add(g) : s.set(g, i), l = (g, s, i, e) => ($(g, s, "write to private field"), e ? e.call(g, i) : s.set(g, i), i), c = (g, s, i) => ($(g, s, "access private method"), i);
var tt = (g, s, i, e) => ({
set _(n) {
l(g, s, n, i);
},
get _() {
return t(g, s, e);
}
});
const D = {
PRESS_TIME: 350,
// ms
DOUBLE_TAP_INTERVAL: 250,
// ms
FLICK_THRESHOLD: 0.75,
// drag speed
DOUBLE_TAP_DRAG_THRESHOLD: 5
// px
}, ht = /* @__PURE__ */ new WeakMap();
var N, V, v, X, L, b, u, F, H, x, T, K, q, w, W, P, B, Y, A, J, k, M, p, R, S, C, I, O, a, rt, lt, at, ot, ct, ut, Q, U, Z, st, ft, z, j, dt, it, G;
class vt {
constructor(s, i = {}) {
f(this, a);
f(this, N);
f(this, V);
f(this, v);
f(this, X, null);
f(this, L, !1);
f(this, b);
f(this, u, {});
f(this, F);
f(this, H);
f(this, x);
f(this, T);
f(this, K);
f(this, q);
f(this, w);
f(this, W);
f(this, P, null);
f(this, B, null);
f(this, Y, 0);
f(this, A, !1);
f(this, J);
f(this, k, {});
f(this, M, {});
f(this, p, /* @__PURE__ */ new Map());
f(this, R, []);
f(this, S);
f(this, C, !1);
f(this, I, null);
nt(this, "gestures", {
press: {
start: () => (l(this, X, "press"), {
type: "press",
data: { x: t(this, x), y: t(this, T) }
}),
move: () => {
},
end: () => {
}
},
tap: {
start: () => {
},
move: () => {
clearTimeout(t(this, b));
},
end: (s, i) => !t(this, L) && i - t(this, F) < D.PRESS_TIME ? (clearTimeout(t(this, b)), i < t(this, H) + D.DOUBLE_TAP_INTERVAL + D.PRESS_TIME ? (l(this, H, null), {
type: "double-tap",
data: { x: t(this, x), y: t(this, T) }
}) : (l(this, H, i), {
type: "tap",
data: { x: t(this, x), y: t(this, T) }
})) : null
},
"two-finger-tap": {
start: () => {
},
move: () => {
},
end: (s, i) => {
if (t(this, R).length === 2 && !t(this, L) && i - t(this, F) < D.PRESS_TIME) {
const e = [...t(this, p).values()].map((n) => ({
x: n.x[0],
y: n.y[0]
}));
if (e.length === 2) {
const n = (e[0].x + e[1].x) / 2, h = (e[0].y + e[1].y) / 2;
return {
type: "two-finger-tap",
data: {
x: n,
y: h,
touches: e
}
};
}
}
return null;
}
},
"long-press": {
start: (s, i) => {
s.length === 1 && l(this, b, setTimeout(() => {
l(this, X, "long-press"), l(this, u, { x: t(this, x), y: t(this, T) }), c(this, a, G).call(this, "long-press", [t(this, u)]);
}, D.PRESS_TIME));
},
move: () => {
clearTimeout(t(this, b));
},
end: () => {
clearTimeout(t(this, b));
}
},
drag: {
start: () => {
},
move: (s) => {
if (s.length !== 1) return null;
const i = s[0], e = i.clientX - t(this, v).left, n = i.clientY - t(this, v).top, { prevX: h, prevY: r } = c(this, a, it).call(this, s, t(this, x), t(this, T));
return l(this, u, {
x: e,
y: n,
startX: t(this, x),
startY: t(this, T),
step: c(this, a, Q).call(this),
speed: c(this, a, U).call(this),
angle: c(this, a, z).call(this, h, r, e, n)
}), t(this, S) || (l(this, S, c(this, a, j).call(this, t(this, x), t(this, T), e, n)), t(this, u).initial_direction = t(this, S)), {
type: "drag",
data: t(this, u)
};
},
end: () => {
var n, h;
if (!t(this, L) || t(this, p).size === 0 || t(this, X) !== "drag") return null;
const s = t(this, p).values().next().value;
if (!((n = s == null ? void 0 : s.x) != null && n.length) || !((h = s == null ? void 0 : s.y) != null && h.length)) return null;
const i = s.x, e = s.y;
return l(this, K, i[i.length - 1]), l(this, q, e[e.length - 1]), t(this, u).endX = t(this, K), t(this, u).endY = t(this, q), t(this, u).speed = c(this, a, U).call(this), t(this, u).initial_direction = t(this, S), i.length > 1 && e.length > 1 && (t(this, u).final_direction = c(this, a, j).call(this, i[i.length - 2], e[e.length - 2], t(this, u).endX, t(this, u).endY)), t(this, u).flick = t(this, u).speed >= D.FLICK_THRESHOLD, {
type: "drag",
data: t(this, u)
};
}
},
pan: {
start: (s) => {
if (s.length < 2) return null;
const { x: i, y: e } = c(this, a, st).call(this, s);
l(this, x, i), l(this, T, e);
},
move: (s) => {
if (s.length < 2) return null;
const { x: i, y: e, touchesArr: n } = c(this, a, st).call(this, s), { prevX: h, prevY: r } = c(this, a, it).call(this, s, t(this, x), t(this, T));
return l(this, u, {
touches: n,
x: i,
y: e,
startX: t(this, x),
startY: t(this, T),
step: c(this, a, Q).call(this),
speed: c(this, a, U).call(this),
angle: c(this, a, z).call(this, h, r, i, e)
}), t(this, S) || (l(this, S, c(this, a, j).call(this, t(this, x), t(this, T), i, e)), t(this, u).initial_direction = t(this, S)), { type: "pan", data: t(this, u) };
},
end: () => {
if (t(this, R).length < 2 || !t(this, L) || t(this, p).size === 0) return null;
const s = [...t(this, p).values()].map((_) => ({
x: _.x[_.x.length - 1],
y: _.y[_.y.length - 1]
})), i = s.length, e = s.reduce((_, m) => _ + m.x, 0) / i, n = s.reduce((_, m) => _ + m.y, 0) / i;
let h = t(this, u).x || t(this, x), r = t(this, u).y || t(this, T), o = 0, d = 0, E = 0;
for (const [_, m] of t(this, p).entries())
m.x.length >= 5 && m.y.length >= 5 && (o += m.x[m.x.length - 5], d += m.y[m.y.length - 5], E++);
E > 0 && (h = o / E, r = d / E);
const y = c(this, a, U).call(this);
return l(this, u, {
touches: s,
x: e,
y: n,
startX: t(this, x),
startY: t(this, T),
step: c(this, a, Q).call(this),
speed: y,
angle: c(this, a, z).call(this, h, r, e, n),
endX: e,
endY: n,
initial_direction: t(this, S),
final_direction: c(this, a, j).call(this, t(this, x), t(this, T), e, n),
flick: y >= D.FLICK_THRESHOLD
}), { type: "pan", data: t(this, u) };
}
},
rotate: {
start: (s) => {
if (s.length !== 2) return;
const [i, e] = s, n = i.clientX, h = i.clientY, r = e.clientX, o = e.clientY;
l(this, w, c(this, a, z).call(this, n, h, r, o)), l(this, W, t(this, w) > 180 ? 360 * t(this, Y) + t(this, w) - 360 : 360 * t(this, Y) + t(this, w));
},
move: (s) => {
if (s.length !== 2) return null;
const [i, e] = s, n = i.clientX, h = i.clientY, r = e.clientX, o = e.clientY, d = c(this, a, z).call(this, n, h, r, o);
c(this, a, dt).call(this, d);
const E = {
touches: [
{ x: n, y: h },
{ x: r, y: o }
],
rotation: t(this, B) - t(this, W),
angleAbsolute: d,
angleRelative: t(this, B)
};
return l(this, u, E), {
type: "rotate",
data: E
};
},
end: () => {
}
},
"pinch-spread": {
start: (s) => {
if (s.length !== 2) return;
const [i, e] = s, n = i.clientX, h = i.clientY, r = e.clientX, o = e.clientY;
l(this, J, c(this, a, Z).call(this, n, h, r, o));
},
move: (s) => {
if (s.length !== 2 || !t(this, k)["pinch-spread"]) return null;
const [i, e] = s, n = i.clientX, h = i.clientY, r = e.clientX, o = e.clientY, d = c(this, a, Z).call(this, n, h, r, o), E = c(this, a, ft).call(this, t(this, J), d), y = {
touches: [
{ x: n, y: h },
{ x: r, y: o }
],
distance: d,
scale: E
};
return l(this, u, y), {
type: "pinch-spread",
data: y
};
},
end: () => t(this, X) !== "pinch-spread" || !t(this, L) || t(this, p).size === 0 ? null : (t(this, u).end = !0, {
type: "pinch-spread",
data: t(this, u)
})
},
"double-tap-and-drag": {
start: (s, i) => {
if (s.length === 1)
if (t(this, H) && i < t(this, H) + D.DOUBLE_TAP_INTERVAL + D.PRESS_TIME) {
l(this, C, !0);
const e = s[0];
l(this, I, {
x: e.clientX - t(this, v).left,
y: e.clientY - t(this, v).top
});
} else
l(this, C, !1);
},
move: (s, i) => {
if (!t(this, C) || s.length !== 1) return null;
const e = s[0], n = e.clientX - t(this, v).left, h = e.clientY - t(this, v).top, r = n - t(this, I).x, o = h - t(this, I).y, d = Math.sqrt(r * r + o * o);
return d > D.DOUBLE_TAP_DRAG_THRESHOLD ? (l(this, X, "double-tap-and-drag"), l(this, u, {
x: n,
y: h,
startX: t(this, I).x,
startY: t(this, I).y,
dx: r,
dy: o,
dist: d
}), {
type: "double-tap-and-drag",
data: t(this, u)
}) : null;
},
end: () => {
l(this, C, !1), l(this, I, null);
}
}
});
// Private methods
f(this, O, (s) => {
var h, r;
(h = t(this, V)) != null && h.preventDefault && s.preventDefault();
const { touches: i, type: e, timeStamp: n } = s;
switch (e) {
case "touchstart":
c(this, a, rt).call(this, i, n);
break;
case "touchmove":
c(this, a, lt).call(this, i, n);
break;
case "touchend":
c(this, a, at).call(this, i, n);
break;
}
c(this, a, ot).call(this, s), (r = t(this, V)) != null && r.visualize && visualize(i);
});
l(this, N, s), l(this, V, i), s && this.on(s);
}
// Public API methods
on(s) {
l(this, N, s), s.addEventListener("touchstart", t(this, O)), s.addEventListener("touchmove", t(this, O)), s.addEventListener("touchend", t(this, O)), ht.set(s, {});
}
off(s) {
s = s || t(this, N), s.removeEventListener("touchstart", t(this, O)), s.removeEventListener("touchmove", t(this, O)), s.removeEventListener("touchend", t(this, O)), ht.delete(s);
}
track(s, i, e) {
t(this, k)[s] = i, e && (e.preventDefault === !0 && (t(this, M)[s] = !0), e.preventDefault === "horizontal" && (t(this, M)[s] = "horizontal"), e.preventDefault === "vertical" && (t(this, M)[s] = "vertical"));
}
untrack(s) {
delete t(this, k)[s];
}
}
N = new WeakMap(), V = new WeakMap(), v = new WeakMap(), X = new WeakMap(), L = new WeakMap(), b = new WeakMap(), u = new WeakMap(), F = new WeakMap(), H = new WeakMap(), x = new WeakMap(), T = new WeakMap(), K = new WeakMap(), q = new WeakMap(), w = new WeakMap(), W = new WeakMap(), P = new WeakMap(), B = new WeakMap(), Y = new WeakMap(), A = new WeakMap(), J = new WeakMap(), k = new WeakMap(), M = new WeakMap(), p = new WeakMap(), R = new WeakMap(), S = new WeakMap(), C = new WeakMap(), I = new WeakMap(), O = new WeakMap(), a = new WeakSet(), rt = function(s, i) {
l(this, F, i), l(this, P, null), l(this, B, null), l(this, Y, 0), l(this, A, !1), l(this, X, null), c(this, a, ct).call(this, s, i);
const e = Object.values(this.gestures);
for (let n = 0; n < e.length; n++) {
const h = e[n];
if (h.start) {
const r = h.start(s, i);
r && (l(this, X, r.type), c(this, a, G).call(this, r.type, [r.data, t(this, p)]));
}
}
}, lt = function(s, i) {
l(this, L, !0), c(this, a, ut).call(this, s, i);
const e = Object.values(this.gestures);
for (let n = 0; n < e.length; n++) {
const h = e[n];
if (h.move) {
const r = h.move(s, i);
r && (l(this, X, r.type), c(this, a, G).call(this, r.type, [r.data, t(this, p)]));
}
}
}, at = function(s, i) {
const e = Object.values(this.gestures);
for (let n = 0; n < e.length; n++) {
const h = e[n];
if (h.end) {
const r = h.end(s, i);
r && (l(this, X, r.type), c(this, a, G).call(this, r.type, [r.data, t(this, p)]));
}
}
s.length === 0 && (l(this, p, /* @__PURE__ */ new Map()), l(this, R, [])), l(this, L, !1), l(this, S, null);
}, ot = function(s) {
if (t(this, M)[t(this, X)] === !0) {
s.preventDefault();
return;
}
const i = t(this, u).angle;
i == null || Number.isNaN(i) || (t(this, M)[t(this, X)] === "horizontal" ? (i > 45 && i < 135 || i > 225 && i < 315) && s.preventDefault() : t(this, M)[t(this, X)] === "vertical" && (i > 315 || i < 45 || i > 135 && i < 225) && s.preventDefault());
}, ct = function(s, i) {
l(this, v, t(this, N).getBoundingClientRect());
for (const e of s) {
const n = e.identifier;
if (!t(this, p).has(n)) {
const h = e.clientX - t(this, v).left, r = e.clientY - t(this, v).top;
l(this, x, h), l(this, T, r), t(this, p).set(n, {
x: [h],
y: [r],
t: [i]
}), t(this, R).push(n);
}
}
}, ut = function(s, i) {
if (t(this, p).size !== 0)
for (const e of s) {
const n = t(this, p).get(e.identifier);
n && (n.x.push(e.clientX - t(this, v).left), n.y.push(e.clientY - t(this, v).top), n.t.push(i));
}
}, Q = function() {
let s = 0;
const i = t(this, R).length;
for (let e = 0; e < i; e++) {
const n = t(this, R)[e], h = t(this, p).get(n);
if (h && h.x.length > 1) {
const r = h.x;
s = Math.abs(r[r.length - 1] - r[r.length - 2]);
break;
}
}
return s;
}, U = function() {
var E, y, _;
const s = t(this, R)[0], i = t(this, p).get(s);
if (!((E = i == null ? void 0 : i.x) != null && E.length) || !((y = i == null ? void 0 : i.y) != null && y.length) || !((_ = i == null ? void 0 : i.t) != null && _.length)) return 0;
const e = Math.min(5, i.x.length), n = i.x.slice(-e), h = i.y.slice(-e), r = i.t.slice(-e), o = r[r.length - 1] - r[0];
return o === 0 ? 0 : c(this, a, Z).call(this, n[0], h[0], n[n.length - 1], h[h.length - 1]) / o;
}, Z = function(s, i, e, n) {
return Math.hypot(e - s, n - i);
}, st = function(s) {
const i = s.length;
let e = 0, n = 0;
for (let o = 0; o < i; o++)
e += s[o].clientX - t(this, v).left, n += s[o].clientY - t(this, v).top;
const h = e / i, r = n / i;
return {
x: h,
y: r,
touchesArr: Array.from(s).map((o) => ({
x: o.clientX - t(this, v).left,
y: o.clientY - t(this, v).top
}))
};
}, ft = function(s, i) {
return i / s;
}, z = function(s, i, e, n) {
const h = e - s, r = n - i;
let d = Math.atan2(r, h) * 180 / Math.PI + 90;
return d < 0 && (d += 360), d > 360 && (d -= 360), d;
}, j = function(s, i, e, n) {
const h = c(this, a, z).call(this, s, i, e, n);
if (h >= 315 || h < 45) return "top";
if (h >= 45 && h < 135) return "right";
if (h >= 135 && h < 225) return "bottom";
if (h >= 225 && h < 315) return "left";
}, dt = function(s) {
if (t(this, P) === null) {
l(this, P, s);
return;
}
s - t(this, P) <= -180 ? t(this, A) ? (l(this, Y, 0), l(this, A, !1)) : tt(this, Y)._++ : s - t(this, P) >= 180 && (t(this, Y) === 0 && !t(this, A) ? l(this, A, !0) : tt(this, Y)._--), l(this, B, t(this, A) || t(this, Y) < 0 ? 360 * t(this, Y) + s - 360 : 360 * t(this, Y) + s), l(this, P, s);
}, it = function(s, i, e) {
let n = i, h = e;
if (s.length > 1) {
let r = 0, o = 0, d = 0;
for (const E of s) {
const y = t(this, p).get(E.identifier);
y && y.x.length >= 5 && y.y.length >= 5 && (r += y.x[y.x.length - 5], o += y.y[y.y.length - 5], d++);
}
if (d > 0)
return n = r / d, h = o / d, { prevX: n, prevY: h };
r = 0, o = 0, d = 0;
for (const E of s) {
const y = t(this, p).get(E.identifier);
y && y.x.length > 0 && y.y.length > 0 && (r += y.x[0], o += y.y[0], d++);
}
d > 0 && (n = r / d, h = o / d);
} else if (s.length === 1) {
const r = s[0].identifier, o = t(this, p).get(r);
o && o.x.length > 1 && o.y.length > 1 && (o.x.length >= 5 ? (n = o.x[o.x.length - 5], h = o.y[o.y.length - 5]) : (n = o.x[0], h = o.y[0]));
}
return { prevX: n, prevY: h };
}, G = function(s, i) {
t(this, p).size > 0 && t(this, k)[s] && t(this, k)[s].apply(this, i);
};
export {
vt as default
};