pixi-viewport
Version:
A highly configurable viewport/2D camera designed to work with pixi.js. Features include dragging, pinch-to-zoom, mouse wheel zooming, decelerated dragging, follow target, snap to point, snap to zoom, clamping, bouncing on edges, and move on mouse edges.
1,182 lines • 92.4 kB
JavaScript
import { Rectangle as y, Point as c, Ticker as H, Container as b } from "pixi.js";
var S = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
function M(l) {
return l && l.__esModule && Object.prototype.hasOwnProperty.call(l, "default") ? l.default : l;
}
var W = { exports: {} };
(function(l, t) {
(function() {
var e, n;
n = function(i) {
return l.exports = i;
}, e = {
linear: function(i, s, h, o) {
return h * i / o + s;
},
easeInQuad: function(i, s, h, o) {
return h * (i /= o) * i + s;
},
easeOutQuad: function(i, s, h, o) {
return -h * (i /= o) * (i - 2) + s;
},
easeInOutQuad: function(i, s, h, o) {
return (i /= o / 2) < 1 ? h / 2 * i * i + s : -h / 2 * (--i * (i - 2) - 1) + s;
},
easeInCubic: function(i, s, h, o) {
return h * (i /= o) * i * i + s;
},
easeOutCubic: function(i, s, h, o) {
return h * ((i = i / o - 1) * i * i + 1) + s;
},
easeInOutCubic: function(i, s, h, o) {
return (i /= o / 2) < 1 ? h / 2 * i * i * i + s : h / 2 * ((i -= 2) * i * i + 2) + s;
},
easeInQuart: function(i, s, h, o) {
return h * (i /= o) * i * i * i + s;
},
easeOutQuart: function(i, s, h, o) {
return -h * ((i = i / o - 1) * i * i * i - 1) + s;
},
easeInOutQuart: function(i, s, h, o) {
return (i /= o / 2) < 1 ? h / 2 * i * i * i * i + s : -h / 2 * ((i -= 2) * i * i * i - 2) + s;
},
easeInQuint: function(i, s, h, o) {
return h * (i /= o) * i * i * i * i + s;
},
easeOutQuint: function(i, s, h, o) {
return h * ((i = i / o - 1) * i * i * i * i + 1) + s;
},
easeInOutQuint: function(i, s, h, o) {
return (i /= o / 2) < 1 ? h / 2 * i * i * i * i * i + s : h / 2 * ((i -= 2) * i * i * i * i + 2) + s;
},
easeInSine: function(i, s, h, o) {
return -h * Math.cos(i / o * (Math.PI / 2)) + h + s;
},
easeOutSine: function(i, s, h, o) {
return h * Math.sin(i / o * (Math.PI / 2)) + s;
},
easeInOutSine: function(i, s, h, o) {
return -h / 2 * (Math.cos(Math.PI * i / o) - 1) + s;
},
easeInExpo: function(i, s, h, o) {
return i === 0 ? s : h * Math.pow(2, 10 * (i / o - 1)) + s;
},
easeOutExpo: function(i, s, h, o) {
return i === o ? s + h : h * (-Math.pow(2, -10 * i / o) + 1) + s;
},
easeInOutExpo: function(i, s, h, o) {
return (i /= o / 2) < 1 ? h / 2 * Math.pow(2, 10 * (i - 1)) + s : h / 2 * (-Math.pow(2, -10 * --i) + 2) + s;
},
easeInCirc: function(i, s, h, o) {
return -h * (Math.sqrt(1 - (i /= o) * i) - 1) + s;
},
easeOutCirc: function(i, s, h, o) {
return h * Math.sqrt(1 - (i = i / o - 1) * i) + s;
},
easeInOutCirc: function(i, s, h, o) {
return (i /= o / 2) < 1 ? -h / 2 * (Math.sqrt(1 - i * i) - 1) + s : h / 2 * (Math.sqrt(1 - (i -= 2) * i) + 1) + s;
},
easeInElastic: function(i, s, h, o) {
var r, a, p;
return p = 1.70158, a = 0, r = h, i === 0 || (i /= o), a || (a = o * 0.3), r < Math.abs(h) ? (r = h, p = a / 4) : p = a / (2 * Math.PI) * Math.asin(h / r), -(r * Math.pow(2, 10 * (i -= 1)) * Math.sin((i * o - p) * (2 * Math.PI) / a)) + s;
},
easeOutElastic: function(i, s, h, o) {
var r, a, p;
return p = 1.70158, a = 0, r = h, i === 0 || (i /= o), a || (a = o * 0.3), r < Math.abs(h) ? (r = h, p = a / 4) : p = a / (2 * Math.PI) * Math.asin(h / r), r * Math.pow(2, -10 * i) * Math.sin((i * o - p) * (2 * Math.PI) / a) + h + s;
},
easeInOutElastic: function(i, s, h, o) {
var r, a, p;
return p = 1.70158, a = 0, r = h, i === 0 || (i /= o / 2), a || (a = o * (0.3 * 1.5)), r < Math.abs(h) ? (r = h, p = a / 4) : p = a / (2 * Math.PI) * Math.asin(h / r), i < 1 ? -0.5 * (r * Math.pow(2, 10 * (i -= 1)) * Math.sin((i * o - p) * (2 * Math.PI) / a)) + s : r * Math.pow(2, -10 * (i -= 1)) * Math.sin((i * o - p) * (2 * Math.PI) / a) * 0.5 + h + s;
},
easeInBack: function(i, s, h, o, r) {
return r === void 0 && (r = 1.70158), h * (i /= o) * i * ((r + 1) * i - r) + s;
},
easeOutBack: function(i, s, h, o, r) {
return r === void 0 && (r = 1.70158), h * ((i = i / o - 1) * i * ((r + 1) * i + r) + 1) + s;
},
easeInOutBack: function(i, s, h, o, r) {
return r === void 0 && (r = 1.70158), (i /= o / 2) < 1 ? h / 2 * (i * i * (((r *= 1.525) + 1) * i - r)) + s : h / 2 * ((i -= 2) * i * (((r *= 1.525) + 1) * i + r) + 2) + s;
},
easeInBounce: function(i, s, h, o) {
var r;
return r = e.easeOutBounce(o - i, 0, h, o), h - r + s;
},
easeOutBounce: function(i, s, h, o) {
return (i /= o) < 1 / 2.75 ? h * (7.5625 * i * i) + s : i < 2 / 2.75 ? h * (7.5625 * (i -= 1.5 / 2.75) * i + 0.75) + s : i < 2.5 / 2.75 ? h * (7.5625 * (i -= 2.25 / 2.75) * i + 0.9375) + s : h * (7.5625 * (i -= 2.625 / 2.75) * i + 0.984375) + s;
},
easeInOutBounce: function(i, s, h, o) {
var r;
return i < o / 2 ? (r = e.easeInBounce(i * 2, 0, h, o), r * 0.5 + s) : (r = e.easeOutBounce(i * 2 - o, 0, h, o), r * 0.5 + h * 0.5 + s);
}
}, n(e);
}).call(S);
})(W);
var O = W.exports;
const v = /* @__PURE__ */ M(O);
function x(l, t) {
if (l) {
if (typeof l == "function")
return l;
if (typeof l == "string")
return v[l];
} else
return v[t];
}
class P {
constructor(t) {
this.viewport = t, this.touches = [], this.addListeners();
}
/** Add input listeners */
addListeners() {
this.viewport.eventMode = "static", this.viewport.forceHitArea || (this.viewport.hitArea = new y(0, 0, this.viewport.worldWidth, this.viewport.worldHeight)), this.viewport.on("pointerdown", this.down, this), this.viewport.options.allowPreserveDragOutside ? this.viewport.on("globalpointermove", this.move, this) : this.viewport.on("pointermove", this.move, this), this.viewport.on("pointerup", this.up, this), this.viewport.on("pointerupoutside", this.up, this), this.viewport.on("pointercancel", this.up, this), this.viewport.options.allowPreserveDragOutside || this.viewport.on("pointerleave", this.up, this), this.wheelFunction = (t) => this.handleWheel(t), this.viewport.options.events.domElement.addEventListener(
"wheel",
this.wheelFunction,
{ passive: this.viewport.options.passiveWheel }
), this.isMouseDown = !1;
}
/**
* Removes all event listeners from viewport
* (useful for cleanup of wheel when removing viewport)
*/
destroy() {
var t;
(t = this.viewport.options.events.domElement) == null || t.removeEventListener("wheel", this.wheelFunction);
}
/**
* handle down events for viewport
*
* @param {PIXI.FederatedPointerEvent} event
*/
down(t) {
if (this.viewport.pause || !this.viewport.visible)
return;
if (t.pointerType === "mouse" ? this.isMouseDown = !0 : this.get(t.pointerId) || this.touches.push({ id: t.pointerId, last: null }), this.count() === 1) {
this.last = t.global.clone();
const n = this.viewport.plugins.get("decelerate", !0), i = this.viewport.plugins.get("bounce", !0);
(!n || !n.isActive()) && (!i || !i.isActive()) ? this.clickedAvailable = !0 : this.clickedAvailable = !1;
} else
this.clickedAvailable = !1;
this.viewport.plugins.down(t) && this.viewport.options.stopPropagation && t.stopPropagation();
}
/** Clears all pointer events */
clear() {
this.isMouseDown = !1, this.touches = [], this.last = null;
}
/**
* @param {number} change
* @returns whether change exceeds threshold
*/
checkThreshold(t) {
return Math.abs(t) >= this.viewport.threshold;
}
/** Handle move events for viewport */
move(t) {
if (this.viewport.pause || !this.viewport.visible)
return;
const e = this.viewport.plugins.move(t);
if (this.clickedAvailable && this.last) {
const n = t.global.x - this.last.x, i = t.global.y - this.last.y;
(this.checkThreshold(n) || this.checkThreshold(i)) && (this.clickedAvailable = !1);
}
e && this.viewport.options.stopPropagation && t.stopPropagation();
}
/** Handle up events for viewport */
up(t) {
if (this.viewport.pause || !this.viewport.visible)
return;
t.pointerType === "mouse" && (this.isMouseDown = !1), t.pointerType !== "mouse" && this.remove(t.pointerId);
const e = this.viewport.plugins.up(t);
this.clickedAvailable && this.count() === 0 && this.last && (this.viewport.emit("clicked", {
event: t,
screen: this.last,
world: this.viewport.toWorld(this.last),
viewport: this.viewport
}), this.clickedAvailable = !1), e && this.viewport.options.stopPropagation && t.stopPropagation();
}
/** Gets pointer position if this.interaction is set */
getPointerPosition(t) {
const e = new c();
return this.viewport.options.events.mapPositionToPoint(e, t.clientX, t.clientY), e;
}
/** Handle wheel events */
handleWheel(t) {
if (this.viewport.pause || !this.viewport.visible)
return;
const e = this.viewport.toLocal(this.getPointerPosition(t));
this.viewport.left <= e.x && e.x <= this.viewport.right && this.viewport.top <= e.y && e.y <= this.viewport.bottom && this.viewport.plugins.wheel(t) && !this.viewport.options.passiveWheel && t.preventDefault();
}
pause() {
this.touches = [], this.isMouseDown = !1;
}
/** Get touch by id */
get(t) {
for (const e of this.touches)
if (e.id === t)
return e;
return null;
}
/** Remove touch by number */
remove(t) {
for (let e = 0; e < this.touches.length; e++)
if (this.touches[e].id === t) {
this.touches.splice(e, 1);
return;
}
}
/**
* @returns {number} count of mouse/touch pointers that are down on the viewport
*/
count() {
return (this.isMouseDown ? 1 : 0) + this.touches.length;
}
}
const m = [
"drag",
"pinch",
"wheel",
"follow",
"mouse-edges",
"decelerate",
"animate",
"bounce",
"snap-zoom",
"clamp-zoom",
"snap",
"clamp"
];
class C {
/** This is called by {@link Viewport} to initialize the {@link Viewport.plugins plugins}. */
constructor(t) {
this.viewport = t, this.list = [], this.plugins = {};
}
/**
* Inserts a named plugin or a user plugin into the viewport
* default plugin order: 'drag', 'pinch', 'wheel', 'follow', 'mouse-edges', 'decelerate', 'bounce',
* 'snap-zoom', 'clamp-zoom', 'snap', 'clamp'
*
* @param {string} name of plugin
* @param {Plugin} plugin - instantiated Plugin class
* @param {number} index to insert userPlugin (otherwise inserts it at the end)
*/
add(t, e, n = m.length) {
const i = this.plugins[t];
i && i.destroy(), this.plugins[t] = e;
const s = m.indexOf(t);
s !== -1 && m.splice(s, 1), m.splice(n, 0, t), this.sort();
}
/**
* Get plugin
*
* @param {string} name of plugin
* @param {boolean} [ignorePaused] return null if plugin is paused
*/
get(t, e) {
var n;
return e && (n = this.plugins[t]) != null && n.paused ? null : this.plugins[t];
}
/**
* Update all active plugins
*
* @internal
* @ignore
* @param {number} elapsed type in milliseconds since last update
*/
update(t) {
for (const e of this.list)
e.update(t);
}
/**
* Resize all active plugins
*
* @internal
* @ignore
*/
resize() {
for (const t of this.list)
t.resize();
}
/** Clamps and resets bounce and decelerate (as needed) after manually moving viewport */
reset() {
for (const t of this.list)
t.reset();
}
/** removes all installed plugins */
removeAll() {
this.list.forEach((t) => {
t.destroy();
}), this.plugins = {}, this.sort();
}
/**
* Removes installed plugin
*
* @param {string} name of plugin (e.g., 'drag', 'pinch')
*/
remove(t) {
var e;
this.plugins[t] && ((e = this.plugins[t]) == null || e.destroy(), delete this.plugins[t], this.viewport.emit("plugin-remove", t), this.sort());
}
/**
* Pause plugin
*
* @param {string} name of plugin (e.g., 'drag', 'pinch')
*/
pause(t) {
var e;
(e = this.plugins[t]) == null || e.pause();
}
/**
* Resume plugin
*
* @param {string} name of plugin (e.g., 'drag', 'pinch')
*/
resume(t) {
var e;
(e = this.plugins[t]) == null || e.resume();
}
/**
* Sort plugins according to PLUGIN_ORDER
*
* @internal
* @ignore
*/
sort() {
this.list = [];
for (const t of m)
this.plugins[t] && this.list.push(this.plugins[t]);
}
/**
* Handle down for all plugins
*
* @internal
* @ignore
*/
down(t) {
let e = !1;
for (const n of this.list)
n.down(t) && (e = !0);
return e;
}
/**
* Handle move for all plugins
*
* @internal
* @ignore
*/
move(t) {
let e = !1;
for (const n of this.viewport.plugins.list)
n.move(t) && (e = !0);
return e;
}
/**
* Handle up for all plugins
*
* @internal
* @ignore
*/
up(t) {
let e = !1;
for (const n of this.list)
n.up(t) && (e = !0);
return e;
}
/**
* Handle wheel event for all plugins
*
* @internal
* @ignore
*/
wheel(t) {
let e = !1;
for (const n of this.list)
n.wheel(t) && (e = !0);
return e;
}
}
class u {
/** @param {Viewport} parent */
constructor(t) {
this.parent = t, this.paused = !1;
}
/** Called when plugin is removed */
destroy() {
}
/** Handler for pointerdown PIXI event */
down(t) {
return !1;
}
/** Handler for pointermove PIXI event */
move(t) {
return !1;
}
/** Handler for pointerup PIXI event */
up(t) {
return !1;
}
/** Handler for wheel event on div */
wheel(t) {
return !1;
}
/**
* Called on each tick
* @param {number} elapsed time in millisecond since last update
*/
update(t) {
}
/** Called when the viewport is resized */
resize() {
}
/** Called when the viewport is manually moved */
reset() {
}
/** Pause the plugin */
pause() {
this.paused = !0;
}
/** Un-pause the plugin */
resume() {
this.paused = !1;
}
}
const I = {
removeOnInterrupt: !1,
ease: "linear",
time: 1e3
};
class k extends u {
/**
* This is called by {@link Viewport.animate}.
*
* @param parent
* @param options
*/
constructor(t, e = {}) {
super(t), this.startWidth = null, this.startHeight = null, this.deltaWidth = null, this.deltaHeight = null, this.width = null, this.height = null, this.time = 0, this.options = Object.assign({}, I, e), this.options.ease = x(this.options.ease), this.setupPosition(), this.setupZoom(), this.time = 0;
}
/**
* Setup `startX`, `startY`, `deltaX`, `deltaY`, `keepCenter`.
*
* This is called during construction.
*/
setupPosition() {
typeof this.options.position < "u" ? (this.startX = this.parent.center.x, this.startY = this.parent.center.y, this.deltaX = this.options.position.x - this.parent.center.x, this.deltaY = this.options.position.y - this.parent.center.y, this.keepCenter = !1) : this.keepCenter = !0;
}
/**
* Setup `startWidth, `startHeight`, `deltaWidth, `deltaHeight, `width`, `height`.
*
* This is called during construction.
*/
setupZoom() {
this.width = null, this.height = null, typeof this.options.scale < "u" ? this.width = this.parent.screenWidth / this.options.scale : typeof this.options.scaleX < "u" || typeof this.options.scaleY < "u" ? (typeof this.options.scaleX < "u" && (this.width = this.parent.screenWidth / this.options.scaleX), typeof this.options.scaleY < "u" && (this.height = this.parent.screenHeight / this.options.scaleY)) : (typeof this.options.width < "u" && (this.width = this.options.width), typeof this.options.height < "u" && (this.height = this.options.height)), this.width !== null && (this.startWidth = this.parent.screenWidthInWorldPixels, this.deltaWidth = this.width - this.startWidth), this.height !== null && (this.startHeight = this.parent.screenHeightInWorldPixels, this.deltaHeight = this.height - this.startHeight);
}
down() {
return this.options.removeOnInterrupt && this.parent.plugins.remove("animate"), !1;
}
complete() {
this.parent.plugins.remove("animate"), this.width !== null && this.parent.fitWidth(this.width, this.keepCenter, this.height === null), this.height !== null && this.parent.fitHeight(this.height, this.keepCenter, this.width === null), !this.keepCenter && this.options.position && this.parent.moveCenter(this.options.position), this.parent.emit("animate-end", this.parent), this.options.callbackOnComplete && this.options.callbackOnComplete(this.parent);
}
update(t) {
if (this.paused)
return;
this.time += t;
const e = new c(this.parent.scale.x, this.parent.scale.y);
if (this.time >= this.options.time) {
const n = this.parent.width, i = this.parent.height;
this.complete(), (n !== this.parent.width || i !== this.parent.height) && this.parent.emit("zoomed", { viewport: this.parent, original: e, type: "animate" });
} else {
const n = this.options.ease(this.time, 0, 1, this.options.time);
if (this.width !== null) {
const i = this.startWidth, s = this.deltaWidth;
this.parent.fitWidth(
i + s * n,
this.keepCenter,
this.height === null
);
}
if (this.height !== null) {
const i = this.startHeight, s = this.deltaHeight;
this.parent.fitHeight(
i + s * n,
this.keepCenter,
this.width === null
);
}
if (this.width === null ? this.parent.scale.x = this.parent.scale.y : this.height === null && (this.parent.scale.y = this.parent.scale.x), !this.keepCenter) {
const i = this.startX, s = this.startY, h = this.deltaX, o = this.deltaY, r = new c(this.parent.x, this.parent.y);
this.parent.moveCenter(i + h * n, s + o * n), this.parent.emit("moved", { viewport: this.parent, original: r, type: "animate" });
}
(this.width || this.height) && this.parent.emit("zoomed", { viewport: this.parent, original: e, type: "animate" });
}
}
}
const Y = {
sides: "all",
friction: 0.5,
time: 150,
ease: "easeInOutSine",
underflow: "center",
bounceBox: null
};
class X extends u {
/**
* This is called by {@link Viewport.bounce}.
*/
constructor(t, e = {}) {
super(t), this.options = Object.assign({}, Y, e), this.ease = x(this.options.ease, "easeInOutSine"), this.options.sides ? this.options.sides === "all" ? this.top = this.bottom = this.left = this.right = !0 : this.options.sides === "horizontal" ? (this.right = this.left = !0, this.top = this.bottom = !1) : this.options.sides === "vertical" ? (this.left = this.right = !1, this.top = this.bottom = !0) : (this.top = this.options.sides.indexOf("top") !== -1, this.bottom = this.options.sides.indexOf("bottom") !== -1, this.left = this.options.sides.indexOf("left") !== -1, this.right = this.options.sides.indexOf("right") !== -1) : this.left = this.top = this.right = this.bottom = !1;
const n = this.options.underflow.toLowerCase();
n === "center" ? (this.underflowX = 0, this.underflowY = 0) : (this.underflowX = n.indexOf("left") !== -1 ? -1 : n.indexOf("right") !== -1 ? 1 : 0, this.underflowY = n.indexOf("top") !== -1 ? -1 : n.indexOf("bottom") !== -1 ? 1 : 0), this.reset();
}
isActive() {
return this.toX !== null || this.toY !== null;
}
down() {
return this.toX = this.toY = null, !1;
}
up() {
return this.bounce(), !1;
}
update(t) {
if (!this.paused) {
if (this.bounce(), this.toX) {
const e = this.toX;
e.time += t, this.parent.emit("moved", { viewport: this.parent, type: "bounce-x" }), e.time >= this.options.time ? (this.parent.x = e.end, this.toX = null, this.parent.emit("bounce-x-end", this.parent)) : this.parent.x = this.ease(e.time, e.start, e.delta, this.options.time);
}
if (this.toY) {
const e = this.toY;
e.time += t, this.parent.emit("moved", { viewport: this.parent, type: "bounce-y" }), e.time >= this.options.time ? (this.parent.y = e.end, this.toY = null, this.parent.emit("bounce-y-end", this.parent)) : this.parent.y = this.ease(e.time, e.start, e.delta, this.options.time);
}
}
}
/** @internal */
calcUnderflowX() {
let t;
switch (this.underflowX) {
case -1:
t = 0;
break;
case 1:
t = this.parent.screenWidth - this.parent.screenWorldWidth;
break;
default:
t = (this.parent.screenWidth - this.parent.screenWorldWidth) / 2;
}
return t;
}
/** @internal */
calcUnderflowY() {
let t;
switch (this.underflowY) {
case -1:
t = 0;
break;
case 1:
t = this.parent.screenHeight - this.parent.screenWorldHeight;
break;
default:
t = (this.parent.screenHeight - this.parent.screenWorldHeight) / 2;
}
return t;
}
oob() {
const t = this.options.bounceBox;
if (t) {
const e = typeof t.x > "u" ? 0 : t.x, n = typeof t.y > "u" ? 0 : t.y, i = typeof t.width > "u" ? this.parent.worldWidth : t.width, s = typeof t.height > "u" ? this.parent.worldHeight : t.height;
return {
left: this.parent.left < e,
right: this.parent.right > i,
top: this.parent.top < n,
bottom: this.parent.bottom > s,
topLeft: new c(
e * this.parent.scale.x,
n * this.parent.scale.y
),
bottomRight: new c(
i * this.parent.scale.x - this.parent.screenWidth,
s * this.parent.scale.y - this.parent.screenHeight
)
};
}
return {
left: this.parent.left < 0,
right: this.parent.right > this.parent.worldWidth,
top: this.parent.top < 0,
bottom: this.parent.bottom > this.parent.worldHeight,
topLeft: new c(0, 0),
bottomRight: new c(
this.parent.worldWidth * this.parent.scale.x - this.parent.screenWidth,
this.parent.worldHeight * this.parent.scale.y - this.parent.screenHeight
)
};
}
bounce() {
var s, h;
if (this.paused)
return;
let t, e = this.parent.plugins.get("decelerate", !0);
e && (e.x || e.y) && (e.x && e.percentChangeX === ((s = e.options) == null ? void 0 : s.friction) || e.y && e.percentChangeY === ((h = e.options) == null ? void 0 : h.friction)) && (t = this.oob(), (t.left && this.left || t.right && this.right) && (e.percentChangeX = this.options.friction), (t.top && this.top || t.bottom && this.bottom) && (e.percentChangeY = this.options.friction));
const n = this.parent.plugins.get("drag", !0) || {}, i = this.parent.plugins.get("pinch", !0) || {};
if (e = e || {}, !(n != null && n.active) && !(i != null && i.active) && (!this.toX || !this.toY) && (!e.x || !e.y)) {
t = t || this.oob();
const o = t.topLeft, r = t.bottomRight;
if (!this.toX && !e.x) {
let a = null;
t.left && this.left ? a = this.parent.screenWorldWidth < this.parent.screenWidth ? this.calcUnderflowX() : -o.x : t.right && this.right && (a = this.parent.screenWorldWidth < this.parent.screenWidth ? this.calcUnderflowX() : -r.x), a !== null && this.parent.x !== a && (this.toX = { time: 0, start: this.parent.x, delta: a - this.parent.x, end: a }, this.parent.emit("bounce-x-start", this.parent));
}
if (!this.toY && !e.y) {
let a = null;
t.top && this.top ? a = this.parent.screenWorldHeight < this.parent.screenHeight ? this.calcUnderflowY() : -o.y : t.bottom && this.bottom && (a = this.parent.screenWorldHeight < this.parent.screenHeight ? this.calcUnderflowY() : -r.y), a !== null && this.parent.y !== a && (this.toY = { time: 0, start: this.parent.y, delta: a - this.parent.y, end: a }, this.parent.emit("bounce-y-start", this.parent));
}
}
}
reset() {
this.toX = this.toY = null, this.bounce();
}
}
const z = {
left: !1,
right: !1,
top: !1,
bottom: !1,
direction: null,
underflow: "center"
};
class A extends u {
/**
* This is called by {@link Viewport.clamp}.
*/
constructor(t, e = {}) {
super(t), this.options = Object.assign({}, z, e), this.options.direction && (this.options.left = this.options.direction === "x" || this.options.direction === "all" ? !0 : null, this.options.right = this.options.direction === "x" || this.options.direction === "all" ? !0 : null, this.options.top = this.options.direction === "y" || this.options.direction === "all" ? !0 : null, this.options.bottom = this.options.direction === "y" || this.options.direction === "all" ? !0 : null), this.parseUnderflow(), this.last = { x: null, y: null, scaleX: null, scaleY: null }, this.update();
}
parseUnderflow() {
const t = this.options.underflow.toLowerCase();
t === "none" ? this.noUnderflow = !0 : t === "center" ? (this.underflowX = this.underflowY = 0, this.noUnderflow = !1) : (this.underflowX = t.indexOf("left") !== -1 ? -1 : t.indexOf("right") !== -1 ? 1 : 0, this.underflowY = t.indexOf("top") !== -1 ? -1 : t.indexOf("bottom") !== -1 ? 1 : 0, this.noUnderflow = !1);
}
move() {
return this.update(), !1;
}
update() {
if (this.paused || this.parent.x === this.last.x && this.parent.y === this.last.y && this.parent.scale.x === this.last.scaleX && this.parent.scale.y === this.last.scaleY)
return;
const t = new c(this.parent.x, this.parent.y), e = this.parent.plugins.decelerate || {};
if (this.options.left !== null || this.options.right !== null) {
let n = !1;
if (!this.noUnderflow && this.parent.screenWorldWidth < this.parent.screenWidth)
switch (this.underflowX) {
case -1:
this.parent.x !== 0 && (this.parent.x = 0, n = !0);
break;
case 1:
this.parent.x !== this.parent.screenWidth - this.parent.screenWorldWidth && (this.parent.x = this.parent.screenWidth - this.parent.screenWorldWidth, n = !0);
break;
default:
this.parent.x !== (this.parent.screenWidth - this.parent.screenWorldWidth) / 2 && (this.parent.x = (this.parent.screenWidth - this.parent.screenWorldWidth) / 2, n = !0);
}
else
this.options.left !== null && this.parent.left < (this.options.left === !0 ? 0 : this.options.left) && (this.parent.x = -(this.options.left === !0 ? 0 : this.options.left) * this.parent.scale.x, e.x = 0, n = !0), this.options.right !== null && this.parent.right > (this.options.right === !0 ? this.parent.worldWidth : this.options.right) && (this.parent.x = -(this.options.right === !0 ? this.parent.worldWidth : this.options.right) * this.parent.scale.x + this.parent.screenWidth, e.x = 0, n = !0);
n && this.parent.emit("moved", {
viewport: this.parent,
original: t,
type: "clamp-x"
});
}
if (this.options.top !== null || this.options.bottom !== null) {
let n = !1;
if (!this.noUnderflow && this.parent.screenWorldHeight < this.parent.screenHeight)
switch (this.underflowY) {
case -1:
this.parent.y !== 0 && (this.parent.y = 0, n = !0);
break;
case 1:
this.parent.y !== this.parent.screenHeight - this.parent.screenWorldHeight && (this.parent.y = this.parent.screenHeight - this.parent.screenWorldHeight, n = !0);
break;
default:
this.parent.y !== (this.parent.screenHeight - this.parent.screenWorldHeight) / 2 && (this.parent.y = (this.parent.screenHeight - this.parent.screenWorldHeight) / 2, n = !0);
}
else
this.options.top !== null && this.parent.top < (this.options.top === !0 ? 0 : this.options.top) && (this.parent.y = -(this.options.top === !0 ? 0 : this.options.top) * this.parent.scale.y, e.y = 0, n = !0), this.options.bottom !== null && this.parent.bottom > (this.options.bottom === !0 ? this.parent.worldHeight : this.options.bottom) && (this.parent.y = -(this.options.bottom === !0 ? this.parent.worldHeight : this.options.bottom) * this.parent.scale.y + this.parent.screenHeight, e.y = 0, n = !0);
n && this.parent.emit("moved", {
viewport: this.parent,
original: t,
type: "clamp-y"
});
}
this.last.x = this.parent.x, this.last.y = this.parent.y, this.last.scaleX = this.parent.scale.x, this.last.scaleY = this.parent.scale.y;
}
reset() {
this.update();
}
}
const T = {
minWidth: null,
minHeight: null,
maxWidth: null,
maxHeight: null,
minScale: null,
maxScale: null
};
class _ extends u {
/**
* This is called by {@link Viewport.clampZoom}.
*/
constructor(t, e = {}) {
super(t), this.options = Object.assign({}, T, e), this.clamp();
}
resize() {
this.clamp();
}
/** Clamp the viewport scale zoom) */
clamp() {
if (!this.paused) {
if (this.options.minWidth || this.options.minHeight || this.options.maxWidth || this.options.maxHeight) {
let t = this.parent.worldScreenWidth, e = this.parent.worldScreenHeight;
if (this.options.minWidth !== null && t < this.options.minWidth) {
const n = this.parent.scale.x;
this.parent.fitWidth(this.options.minWidth, !1, !1, !0), this.parent.scale.y *= this.parent.scale.x / n, t = this.parent.worldScreenWidth, e = this.parent.worldScreenHeight, this.parent.emit("zoomed", { viewport: this.parent, type: "clamp-zoom" });
}
if (this.options.maxWidth !== null && t > this.options.maxWidth) {
const n = this.parent.scale.x;
this.parent.fitWidth(this.options.maxWidth, !1, !1, !0), this.parent.scale.y *= this.parent.scale.x / n, t = this.parent.worldScreenWidth, e = this.parent.worldScreenHeight, this.parent.emit("zoomed", { viewport: this.parent, type: "clamp-zoom" });
}
if (this.options.minHeight !== null && e < this.options.minHeight) {
const n = this.parent.scale.y;
this.parent.fitHeight(this.options.minHeight, !1, !1, !0), this.parent.scale.x *= this.parent.scale.y / n, t = this.parent.worldScreenWidth, e = this.parent.worldScreenHeight, this.parent.emit("zoomed", { viewport: this.parent, type: "clamp-zoom" });
}
if (this.options.maxHeight !== null && e > this.options.maxHeight) {
const n = this.parent.scale.y;
this.parent.fitHeight(this.options.maxHeight, !1, !1, !0), this.parent.scale.x *= this.parent.scale.y / n, this.parent.emit("zoomed", { viewport: this.parent, type: "clamp-zoom" });
}
} else if (this.options.minScale || this.options.maxScale) {
const t = { x: null, y: null }, e = { x: null, y: null };
if (typeof this.options.minScale == "number")
t.x = this.options.minScale, t.y = this.options.minScale;
else if (this.options.minScale !== null) {
const s = this.options.minScale;
t.x = typeof s.x > "u" ? null : s.x, t.y = typeof s.y > "u" ? null : s.y;
}
if (typeof this.options.maxScale == "number")
e.x = this.options.maxScale, e.y = this.options.maxScale;
else if (this.options.maxScale !== null) {
const s = this.options.maxScale;
e.x = typeof s.x > "u" ? null : s.x, e.y = typeof s.y > "u" ? null : s.y;
}
let n = this.parent.scale.x, i = this.parent.scale.y;
t.x !== null && n < t.x && (n = t.x), e.x !== null && n > e.x && (n = e.x), t.y !== null && i < t.y && (i = t.y), e.y !== null && i > e.y && (i = e.y), (n !== this.parent.scale.x || i !== this.parent.scale.y) && (this.parent.scale.set(n, i), this.parent.emit("zoomed", { viewport: this.parent, type: "clamp-zoom" }));
}
}
}
reset() {
this.clamp();
}
}
const L = {
friction: 0.98,
bounce: 0.8,
minSpeed: 0.01
}, d = 16;
class E extends u {
/**
* This is called by {@link Viewport.decelerate}.
*/
constructor(t, e = {}) {
super(t), this.options = Object.assign({}, L, e), this.saved = [], this.timeSinceRelease = 0, this.reset(), this.parent.on("moved", (n) => this.handleMoved(n));
}
down() {
return this.saved = [], this.x = this.y = null, !1;
}
isActive() {
return !!(this.x || this.y);
}
move() {
if (this.paused)
return !1;
const t = this.parent.input.count();
return (t === 1 || t > 1 && !this.parent.plugins.get("pinch", !0)) && (this.saved.push({ x: this.parent.x, y: this.parent.y, time: performance.now() }), this.saved.length > 60 && this.saved.splice(0, 30)), !1;
}
/** Listener to viewport's "moved" event. */
handleMoved(t) {
if (this.saved.length) {
const e = this.saved[this.saved.length - 1];
t.type === "clamp-x" && t.original ? e.x === t.original.x && (e.x = this.parent.x) : t.type === "clamp-y" && t.original && e.y === t.original.y && (e.y = this.parent.y);
}
}
up() {
if (this.parent.input.count() === 0 && this.saved.length) {
const t = performance.now();
for (const e of this.saved)
if (e.time >= t - 100) {
const n = t - e.time;
this.x = (this.parent.x - e.x) / n, this.y = (this.parent.y - e.y) / n, this.percentChangeX = this.percentChangeY = this.options.friction, this.timeSinceRelease = 0;
break;
}
}
return !1;
}
/**
* Manually activate deceleration, starting from the (x, y) velocity components passed in the options.
*
* @param {object} options
* @param {number} [options.x] - Specify x-component of initial velocity.
* @param {number} [options.y] - Specify y-component of initial velocity.
*/
activate(t) {
t = t || {}, typeof t.x < "u" && (this.x = t.x, this.percentChangeX = this.options.friction), typeof t.y < "u" && (this.y = t.y, this.percentChangeY = this.options.friction);
}
update(t) {
if (this.paused)
return;
const e = this.x || this.y, n = this.timeSinceRelease, i = this.timeSinceRelease + t;
if (this.x) {
const s = this.percentChangeX, h = Math.log(s);
this.parent.x += this.x * d / h * (Math.pow(s, i / d) - Math.pow(s, n / d)), this.x *= Math.pow(this.percentChangeX, t / d);
}
if (this.y) {
const s = this.percentChangeY, h = Math.log(s);
this.parent.y += this.y * d / h * (Math.pow(s, i / d) - Math.pow(s, n / d)), this.y *= Math.pow(this.percentChangeY, t / d);
}
this.timeSinceRelease += t, this.x && this.y ? Math.abs(this.x) < this.options.minSpeed && Math.abs(this.y) < this.options.minSpeed && (this.x = 0, this.y = 0) : (Math.abs(this.x || 0) < this.options.minSpeed && (this.x = 0), Math.abs(this.y || 0) < this.options.minSpeed && (this.y = 0)), e && this.parent.emit("moved", { viewport: this.parent, type: "decelerate" });
}
reset() {
this.x = this.y = null;
}
}
const D = {
direction: "all",
pressDrag: !0,
wheel: !0,
wheelScroll: 1,
reverse: !1,
clampWheel: !1,
underflow: "center",
factor: 1,
mouseButtons: "all",
keyToPress: null,
ignoreKeyToPressOnTouch: !1,
lineHeight: 20,
wheelSwapAxes: !1
};
class U extends u {
/**
* This is called by {@link Viewport.drag}.
*/
constructor(t, e = {}) {
super(t), this.windowEventHandlers = [], this.options = Object.assign({}, D, e), this.moved = !1, this.reverse = this.options.reverse ? 1 : -1, this.xDirection = !this.options.direction || this.options.direction === "all" || this.options.direction === "x", this.yDirection = !this.options.direction || this.options.direction === "all" || this.options.direction === "y", this.keyIsPressed = !1, this.parseUnderflow(), this.mouseButtons(this.options.mouseButtons), this.options.keyToPress && this.handleKeyPresses(this.options.keyToPress);
}
/**
* Handles keypress events and set the keyIsPressed boolean accordingly
*
* @param {array} codes - key codes that can be used to trigger drag event
*/
handleKeyPresses(t) {
const e = (i) => {
t.includes(i.code) && (this.keyIsPressed = !0);
}, n = (i) => {
t.includes(i.code) && (this.keyIsPressed = !1);
};
this.addWindowEventHandler("keyup", n), this.addWindowEventHandler("keydown", e);
}
addWindowEventHandler(t, e) {
typeof window > "u" || (window.addEventListener(t, e), this.windowEventHandlers.push({ event: t, handler: e }));
}
destroy() {
typeof window > "u" || this.windowEventHandlers.forEach(({ event: t, handler: e }) => {
window.removeEventListener(t, e);
});
}
/**
* initialize mousebuttons array
* @param {string} buttons
*/
mouseButtons(t) {
!t || t === "all" ? this.mouse = [!0, !0, !0] : this.mouse = [
t.indexOf("left") !== -1,
t.indexOf("middle") !== -1,
t.indexOf("right") !== -1
];
}
parseUnderflow() {
const t = this.options.underflow.toLowerCase();
t === "center" ? (this.underflowX = 0, this.underflowY = 0) : (t.includes("left") ? this.underflowX = -1 : t.includes("right") ? this.underflowX = 1 : this.underflowX = 0, t.includes("top") ? this.underflowY = -1 : t.includes("bottom") ? this.underflowY = 1 : this.underflowY = 0);
}
/**
* @param {PIXI.FederatedPointerEvent} event
* @returns {boolean}
*/
checkButtons(t) {
const e = t.pointerType === "mouse", n = this.parent.input.count();
return !!((n === 1 || n > 1 && !this.parent.plugins.get("pinch", !0)) && (!e || this.mouse[t.button]));
}
/**
* @param {PIXI.FederatedPointerEvent} event
* @returns {boolean}
*/
checkKeyPress(t) {
return !this.options.keyToPress || this.keyIsPressed || this.options.ignoreKeyToPressOnTouch && t.data.pointerType === "touch";
}
down(t) {
return this.paused || !this.options.pressDrag ? !1 : this.checkButtons(t) && this.checkKeyPress(t) ? (this.last = { x: t.global.x, y: t.global.y }, (this.parent.parent || this.parent).toLocal(
this.last,
void 0,
this.last
), this.current = t.pointerId, !0) : (this.last = null, !1);
}
get active() {
return this.moved;
}
move(t) {
if (this.paused || !this.options.pressDrag)
return !1;
if (this.last && this.current === t.data.pointerId) {
const e = t.global.x, n = t.global.y, i = this.parent.input.count();
if (i === 1 || i > 1 && !this.parent.plugins.get("pinch", !0)) {
const s = { x: e, y: n };
(this.parent.parent || this.parent).toLocal(
s,
void 0,
s
);
const h = s.x - this.last.x, o = s.y - this.last.y;
if (this.moved || this.xDirection && this.parent.input.checkThreshold(h) || this.yDirection && this.parent.input.checkThreshold(o))
return this.xDirection && (this.parent.x += (s.x - this.last.x) * this.options.factor), this.yDirection && (this.parent.y += (s.y - this.last.y) * this.options.factor), this.last = s, this.moved || this.parent.emit("drag-start", {
event: t,
screen: new c(this.last.x, this.last.y),
world: this.parent.toWorld(new c(this.last.x, this.last.y)),
viewport: this.parent
}), this.moved = !0, this.parent.emit("moved", { viewport: this.parent, type: "drag" }), !0;
} else
this.moved = !1;
}
return !1;
}
up(t) {
if (this.paused)
return !1;
const e = this.parent.input.touches;
if (e.length === 1) {
const n = e[0];
return n.last && (this.last = { x: n.last.x, y: n.last.y }, this.current = n.id), this.moved = !1, !0;
} else if (this.last && this.moved) {
const n = new c(this.last.x, this.last.y);
return (this.parent.parent || this.parent).toGlobal(n, n, !0), this.parent.emit("drag-end", {
event: t,
screen: n,
world: this.parent.toWorld(n),
viewport: this.parent
}), this.last = null, this.moved = !1, !0;
}
return !1;
}
wheel(t) {
if (this.paused)
return !1;
if (this.options.wheel) {
const e = this.parent.plugins.get("wheel", !0);
if (!e || !e.options.wheelZoom && !t.ctrlKey) {
const n = t.deltaMode ? this.options.lineHeight : 1, i = [t.deltaX, t.deltaY], [s, h] = this.options.wheelSwapAxes ? i.reverse() : i;
return this.xDirection && (this.parent.x += s * n * this.options.wheelScroll * this.reverse), this.yDirection && (this.parent.y += h * n * this.options.wheelScroll * this.reverse), this.options.clampWheel && this.clamp(), this.parent.emit("wheel-scroll", this.parent), this.parent.emit("moved", { viewport: this.parent, type: "wheel" }), this.parent.options.passiveWheel || t.preventDefault(), this.parent.options.stopPropagation && t.stopPropagation(), !0;
}
}
return !1;
}
resume() {
this.last = null, this.paused = !1;
}
clamp() {
const t = this.parent.plugins.get("decelerate", !0) || {};
if (this.options.clampWheel !== "y")
if (this.parent.screenWorldWidth < this.parent.screenWidth)
switch (this.underflowX) {
case -1:
this.parent.x = 0;
break;
case 1:
this.parent.x = this.parent.screenWidth - this.parent.screenWorldWidth;
break;
default:
this.parent.x = (this.parent.screenWidth - this.parent.screenWorldWidth) / 2;
}
else
this.parent.left < 0 ? (this.parent.x = 0, t.x = 0) : this.parent.right > this.parent.worldWidth && (this.parent.x = -this.parent.worldWidth * this.parent.scale.x + this.parent.screenWidth, t.x = 0);
if (this.options.clampWheel !== "x")
if (this.parent.screenWorldHeight < this.parent.screenHeight)
switch (this.underflowY) {
case -1:
this.parent.y = 0;
break;
case 1:
this.parent.y = this.parent.screenHeight - this.parent.screenWorldHeight;
break;
default:
this.parent.y = (this.parent.screenHeight - this.parent.screenWorldHeight) / 2;
}
else
this.parent.top < 0 && (this.parent.y = 0, t.y = 0), this.parent.bottom > this.parent.worldHeight && (this.parent.y = -this.parent.worldHeight * this.parent.scale.y + this.parent.screenHeight, t.y = 0);
}
}
const F = {
speed: 0,
acceleration: null,
radius: null
};
class B extends u {
/**
* This is called by {@link Viewport.follow}.
*
* @param parent
* @param target - target to follow
* @param options
*/
constructor(t, e, n = {}) {
super(t), this.target = e, this.options = Object.assign({}, F, n), this.velocity = { x: 0, y: 0 };
}
update(t) {
if (this.paused)
return;
const e = this.parent.center;
let n = this.target.x, i = this.target.y;
if (this.options.radius)
if (Math.sqrt(Math.pow(this.target.y - e.y, 2) + Math.pow(this.target.x - e.x, 2)) > this.options.radius) {
const r = Math.atan2(this.target.y - e.y, this.target.x - e.x);
n = this.target.x - Math.cos(r) * this.options.radius, i = this.target.y - Math.sin(r) * this.options.radius;
} else
return;
const s = n - e.x, h = i - e.y;
if (s || h)
if (this.options.speed)
if (this.options.acceleration) {
const o = Math.atan2(i - e.y, n - e.x), r = Math.sqrt(Math.pow(s, 2) + Math.pow(h, 2));
if (r) {
const a = (Math.pow(this.velocity.x, 2) + Math.pow(this.velocity.y, 2)) / (2 * this.options.acceleration);
r > a ? this.velocity = {
x: Math.min(this.velocity.x + (this.options.acceleration * t, this.options.speed)),
y: Math.min(this.velocity.y + (this.options.acceleration * t, this.options.speed))
} : this.velocity = {
x: Math.max(this.velocity.x - this.options.acceleration * this.options.speed, 0),
y: Math.max(this.velocity.y - this.options.acceleration * this.options.speed, 0)
};
const p = Math.cos(o) * this.velocity.x, f = Math.sin(o) * this.velocity.y, g = Math.abs(p) > Math.abs(s) ? n : e.x + p, w = Math.abs(f) > Math.abs(h) ? i : e.y + f;
this.parent.moveCenter(g, w), this.parent.emit("moved", { viewport: this.parent, type: "follow" });
}
} else {
const o = Math.atan2(i - e.y, n - e.x), r = Math.cos(o) * this.options.speed, a = Math.sin(o) * this.options.speed, p = Math.abs(r) > Math.abs(s) ? n : e.x + r, f = Math.abs(a) > Math.abs(h) ? i : e.y + a;
this.parent.moveCenter(p, f), this.parent.emit("moved", { viewport: this.parent, type: "follow" });
}
else
this.parent.moveCenter(n, i), this.parent.emit("moved", { viewport: this.parent, type: "follow" });
}
}
const N = {
radius: null,
distance: null,
top: null,
bottom: null,
left: null,
right: null,
speed: 8,
reverse: !1,
noDecelerate: !1,
linear: !1,
allowButtons: !1
};
class V extends u {
/**
* This is called by {@link Viewport.mouseEdges}.
*/
constructor(t, e = {}) {
super(t), this.options = Object.assign({}, N, e), this.reverse = this.options.reverse ? 1 : -1, this.radiusSquared = typeof this.options.radius == "number" ? Math.pow(this.options.radius, 2) : null, this.resize();
}
resize() {
const t = this.options.distance;
t !== null ? (this.left = t, this.top = t, this.right = this.parent.screenWidth - t, this.bottom = this.parent.screenHeight - t) : this.options.radius || (this.left = this.options.left, this.top = this.options.top, this.right = this.options.right === null ? null : this.parent.screenWidth - this.options.right, this.bottom = this.options.bottom === null ? null : this.parent.screenHeight - this.options.bottom);
}
down() {
return this.paused || this.options.allowButtons || (this.horizontal = this.vertical = null), !1;
}
move(t) {
if (this.paused || t.pointerType !== "mouse" && t.pointerId !== 1 || !this.options.allowButtons && t.buttons !== 0)
return !1;
const e = t.global.x, n = t.global.y;
if (this.radiusSquared) {
const i = this.parent.toScreen(this.parent.center);
if (Math.pow(i.x - e, 2) + Math.pow(i.y - n, 2) >= this.radiusSquared) {
const h = Math.atan2(i.y - n, i.x - e);
this.options.linear ? (this.horizontal = Math.round(Math.cos(h)) * this.options.speed * this.reverse * (60 / 1e3), this.vertical = Math.round(Math.sin(h)) * this.options.speed * this.reverse * (60 / 1e3)) : (this.horizontal = Math.cos(h) * this.options.speed * this.reverse * (60 / 1e3), this.vertical = Math.sin(h) * this.options.speed * this.reverse * (60 / 1e3));
} else
this.horizontal && this.decelerateHorizontal(), this.vertical && this.decelerateVertical(), this.horizontal = this.vertical = 0;
} else
this.left !== null && e < this.left ? this.horizontal = Number(this.reverse) * this.options.speed * (60 / 1e3) : this.right !== null && e > this.right ? this.horizontal = -1 * this.reverse * this.options.speed * (60 / 1e3) : (this.decelerateHorizontal(), this.horizontal = 0), this.top !== null && n < this.top ? this.vertical = Number(this.reverse) * this.options.speed * (60 / 1e3) : this.bottom !== null && n > this.bottom ? this.vertical = -1 * this.reverse * this.options.speed * (60 / 1e3) : (this.decelerateVertical(), this.vertical = 0);
return !1;
}
decelerateHorizontal() {
const t = this.parent.plugins.get("decelerate", !0);
this.horizontal && t && !this.options.noDecelerate && t.activate({ x: this.horizontal * this.options.speed * this.reverse / (1e3 / 60) });
}
decelerateVertical() {
const t = this.parent.plugins.get("decelerate", !0);
this.vertical && t && !this.options.noDecelerate && t.activate({ y: this.vertical * this.options.speed * this.reverse / (1e3 / 60) });
}
up() {
return this.paused || (this.horizontal && this.decelerateHorizontal(), this.vertical && this.decelerateVertical(), this.horizontal = this.vertical = null), !1;
}
update() {
if (!this.paused && (this.horizontal || this.vertical)) {
const t = this.parent.center;
this.horizontal && (t.x += this.horizontal * this.options.speed), this.vertical && (t.y += this.vertical * this.options.speed), this.parent.moveCenter(t), this.parent.emit("moved", { viewport: this.parent, type: "mouse-edges" });
}
}
}
const Z = {
noDrag: !1,
percent: 1,
center: null,
factor: 1,
axis: "all"
}, R = new c();
class j extends u {
/**
* This is called by {@link Viewport.pinch}.
*/
constructor(t, e = {}) {
super(t), this.active = !1, this.pinching = !1, this.moved = !1, this.options = Object.assign({}, Z, e);
}
down() {
return this.parent.input.count() >= 2 ? (this.active = !0, !0) : !1;
}
isAxisX() {
return ["all", "x"].includes(this.options.axis);
}
isAxisY() {
return ["all", "y"].includes(this.options.axis);
}
move(t) {
if (this.paused || !this.active)
return !1;
const { x: e, y: n } = (this.parent.parent || this.parent).toLocal(
t.global,
void 0,
R
), i = this.parent.input.touches;
if (i.length >= 2) {
const s = i[0], h = i[1], o = s.last && h.last ? Math.sqrt(
Math.pow(h.last.x - s.last.x, 2) + Math.pow(h.last.y - s.last.y, 2)
) : null;
if (s.id === t.pointerId ? s.last = { x: e, y: n, data: t } : h.id === t.pointerId && (h.last = { x: e, y: n, data: t }), o) {
let r;
const a = new c(
s.last.x + (h.last.x - s.last.x) / 2,
s.last.y + (h.last.y - s.last.y) / 2
);
this.options.center || (r = this.parent.toLocal(
a,
this.parent.parent || this.parent
));
let p = Math.sqrt(
Math.pow(
h.last.x - s.last.x,
2
) + Math.pow(
h.last.y - s.last.y,
2
)
);
p = p === 0 ? p = 1e-10 : p;
const f =