zoooom 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/joystick/dom.ts","../src/styles/joystick.ts","../src/joystick/joystick.ts"],"names":[],"mappings":"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","file":"joystick.cjs","sourcesContent":["/** Default pan distance for keyboard arrows (px) */\nexport const PAN_STEP = 50;\n\n/** Zoom multiplier per discrete step (>1 zooms in) */\nexport const ZOOM_FACTOR = 1.5;\n\n/** Minimum zoom scale (allows slight zoom-out) */\nexport const MIN_SCALE = 0.8;\n\n/** Multiplier beyond native resolution for max zoom */\nexport const OVERSCALE_FACTOR = 2;\n\n/** Friction coefficient for momentum — velocity *= this each frame */\nexport const VELOCITY_DAMPING = 0.85;\n\n/** Sensitivity for trackpad continuous zoom */\nexport const TRACKPAD_SENSITIVITY = 0.002;\n\n/** Joystick panning zone radius (px) */\nexport const JOYSTICK_RADIUS = 60;\n\n/** Center deadzone as fraction of radius */\nexport const JOYSTICK_DEADZONE = 0.1;\n\n/** Maximum joystick panning speed (px/frame) */\nexport const MAX_JOYSTICK_SPEED = 10;\n\n/** Dwell timeout before joystick activates (ms) */\nexport const DWELL_TIMEOUT = 100;\n","/**\n * Create the joystick DOM structure.\n * Returns references to key elements for event binding.\n */\nexport interface JoystickDOM {\n wrap: HTMLElement;\n toggle: HTMLButtonElement;\n disc: HTMLElement;\n innerCircle: HTMLElement;\n zoomIn: HTMLElement;\n zoomOut: HTMLElement;\n}\n\nexport function createJoystickDOM(container: HTMLElement): JoystickDOM {\n // Toggle button (compass)\n const toggle = document.createElement('button');\n toggle.className = 'zoooom-joystick-toggle';\n toggle.setAttribute('aria-label', 'Toggle navigation joystick');\n toggle.setAttribute('aria-expanded', 'false');\n toggle.textContent = '\\u2316'; // ⌖ position indicator\n container.appendChild(toggle);\n\n // Joystick wrapper\n const wrap = document.createElement('div');\n wrap.className = 'zoooom-joystick-wrap';\n wrap.setAttribute('aria-hidden', 'true');\n\n // Disc (outer pan area)\n const disc = document.createElement('div');\n disc.className = 'zoooom-disc';\n disc.setAttribute('role', 'slider');\n disc.setAttribute('aria-label', 'Pan navigation control');\n disc.setAttribute('aria-valuenow', '0');\n disc.setAttribute('aria-valuemin', '0');\n disc.setAttribute('aria-valuemax', '1');\n disc.setAttribute('aria-valuetext', 'Center position — not moving');\n disc.setAttribute('tabindex', '0');\n\n // Inner circle (zoom)\n const innerCircle = document.createElement('div');\n innerCircle.className = 'zoooom-inner-circle';\n\n const zoomOut = document.createElement('div');\n zoomOut.className = 'zoooom-zoom-half zoooom-zoom-out';\n zoomOut.setAttribute('role', 'button');\n zoomOut.setAttribute('aria-label', 'Zoom out');\n zoomOut.setAttribute('tabindex', '0');\n zoomOut.textContent = '\\u2212'; // −\n\n const zoomIn = document.createElement('div');\n zoomIn.className = 'zoooom-zoom-half zoooom-zoom-in';\n zoomIn.setAttribute('role', 'button');\n zoomIn.setAttribute('aria-label', 'Zoom in');\n zoomIn.setAttribute('tabindex', '0');\n zoomIn.textContent = '+';\n\n innerCircle.appendChild(zoomOut);\n innerCircle.appendChild(zoomIn);\n\n // Direction arrows\n const arrows = document.createElement('div');\n arrows.className = 'zoooom-arrows';\n arrows.setAttribute('aria-hidden', 'true');\n for (const dir of ['n', 'e', 's', 'w']) {\n const arrow = document.createElement('div');\n arrow.className = `zoooom-arrow zoooom-arrow-${dir}`;\n arrows.appendChild(arrow);\n }\n\n disc.appendChild(innerCircle);\n disc.appendChild(arrows);\n wrap.appendChild(disc);\n container.appendChild(wrap);\n\n return { wrap, toggle, disc, innerCircle, zoomIn, zoomOut };\n}\n\nexport function destroyJoystickDOM(dom: JoystickDOM): void {\n dom.wrap.remove();\n dom.toggle.remove();\n}\n","export const JOYSTICK_CSS = `\n.zoooom-joystick-wrap {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 100;\n touch-action: none;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.3s ease-out, transform 0.3s ease-out;\n}\n\n.zoooom-joystick-wrap.visible {\n opacity: 1;\n pointer-events: auto;\n}\n\n.zoooom-joystick-toggle {\n position: fixed;\n bottom: 20px;\n left: 50%;\n transform: translateX(-50%);\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.5);\n border: 2px solid rgba(255, 255, 255, 0.6);\n cursor: pointer;\n z-index: 99;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n font-size: 20px;\n font-weight: bold;\n backdrop-filter: blur(4px);\n transition: background 0.2s, box-shadow 0.2s;\n}\n\n.zoooom-joystick-toggle:hover {\n background: rgba(0, 0, 0, 0.7);\n box-shadow: 0 0 12px rgba(0, 0, 0, 0.4);\n}\n\n.zoooom-joystick-toggle:focus-visible {\n outline: 2px solid #2196f3;\n outline-offset: 2px;\n}\n\n.zoooom-disc {\n width: 200px;\n height: 200px;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.4);\n border: 2px solid rgba(255, 255, 255, 0.6);\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n touch-action: none;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);\n}\n\n.zoooom-disc.active {\n border-color: rgba(255, 255, 255, 0.9);\n}\n\n.zoooom-inner-circle {\n width: 72px;\n height: 72px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.5);\n display: flex;\n position: relative;\n z-index: 3;\n}\n\n.zoooom-zoom-half {\n width: 50%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-weight: bold;\n font-size: 22px;\n color: #fff;\n user-select: none;\n transition: background 0.15s;\n}\n\n.zoooom-zoom-half:hover {\n background: rgba(255, 255, 255, 0.25);\n}\n\n.zoooom-zoom-out {\n border-radius: 36px 0 0 36px;\n border-right: 1px solid rgba(255, 255, 255, 0.4);\n}\n\n.zoooom-zoom-in {\n border-radius: 0 36px 36px 0;\n}\n\n.zoooom-arrows {\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n pointer-events: none;\n overflow: hidden;\n}\n\n.zoooom-arrow {\n position: absolute;\n width: 0;\n height: 0;\n opacity: 0;\n transition: opacity 0.2s;\n}\n\n.zoooom-arrow-n {\n top: 14px;\n left: 50%;\n transform: translateX(-50%);\n border-left: 10px solid transparent;\n border-right: 10px solid transparent;\n border-bottom: 14px solid rgba(255, 255, 255, 0.7);\n}\n\n.zoooom-arrow-e {\n top: 50%;\n right: 14px;\n transform: translateY(-50%);\n border-top: 10px solid transparent;\n border-bottom: 10px solid transparent;\n border-left: 14px solid rgba(255, 255, 255, 0.7);\n}\n\n.zoooom-arrow-s {\n bottom: 14px;\n left: 50%;\n transform: translateX(-50%);\n border-left: 10px solid transparent;\n border-right: 10px solid transparent;\n border-top: 14px solid rgba(255, 255, 255, 0.7);\n}\n\n.zoooom-arrow-w {\n top: 50%;\n left: 14px;\n transform: translateY(-50%);\n border-top: 10px solid transparent;\n border-bottom: 10px solid transparent;\n border-right: 14px solid rgba(255, 255, 255, 0.7);\n}\n\n.zoooom-disc.north .zoooom-arrow-n,\n.zoooom-disc.south .zoooom-arrow-s,\n.zoooom-disc.east .zoooom-arrow-e,\n.zoooom-disc.west .zoooom-arrow-w,\n.zoooom-disc.north-east .zoooom-arrow-n,\n.zoooom-disc.north-east .zoooom-arrow-e,\n.zoooom-disc.south-east .zoooom-arrow-s,\n.zoooom-disc.south-east .zoooom-arrow-e,\n.zoooom-disc.south-west .zoooom-arrow-s,\n.zoooom-disc.south-west .zoooom-arrow-w,\n.zoooom-disc.north-west .zoooom-arrow-n,\n.zoooom-disc.north-west .zoooom-arrow-w {\n opacity: 1;\n}\n\n@media (max-width: 768px) {\n .zoooom-disc {\n width: 140px;\n height: 140px;\n }\n\n .zoooom-inner-circle {\n width: 56px;\n height: 56px;\n }\n\n .zoooom-joystick-toggle {\n width: 48px;\n height: 48px;\n font-size: 16px;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .zoooom-joystick-wrap {\n transition: none;\n }\n\n .zoooom-arrow {\n transition: none;\n }\n}\n`;\n\nlet injected = false;\n\nexport function injectJoystickStyles(): void {\n if (injected || typeof document === 'undefined') return;\n const style = document.createElement('style');\n style.setAttribute('data-zoooom-joystick', '');\n style.textContent = JOYSTICK_CSS;\n document.head.appendChild(style);\n injected = true;\n}\n","import type { JoystickOptions } from '../types.js';\nimport { JOYSTICK_RADIUS, JOYSTICK_DEADZONE, MAX_JOYSTICK_SPEED, DWELL_TIMEOUT } from '../core/constants.js';\nimport type { Zoooom } from '../core/Zoooom.js';\nimport { createJoystickDOM, destroyJoystickDOM, type JoystickDOM } from './dom.js';\nimport { injectJoystickStyles } from '../styles/joystick.js';\n\nconst DIRECTIONS = [\n 'east', 'south-east', 'south', 'south-west',\n 'west', 'north-west', 'north', 'north-east',\n] as const;\n\nfunction angleToDirection(angle: number): string {\n if (angle >= -22.5 && angle < 22.5) return 'east';\n if (angle >= 22.5 && angle < 67.5) return 'south-east';\n if (angle >= 67.5 && angle < 112.5) return 'south';\n if (angle >= 112.5 && angle < 157.5) return 'south-west';\n if (angle >= 157.5 || angle < -157.5) return 'west';\n if (angle >= -157.5 && angle < -112.5) return 'north-west';\n if (angle >= -112.5 && angle < -67.5) return 'north';\n return 'north-east';\n}\n\nexport class ZoooomJoystick {\n private viewer: Zoooom;\n private dom: JoystickDOM;\n private options: Required<JoystickOptions>;\n private visible = false;\n private active = false;\n private animationId: number | null = null;\n private joystickX = 0;\n private joystickY = 0;\n private currentDirection = '';\n private dwellTimer: ReturnType<typeof setTimeout> | null = null;\n private isDwelling = false;\n private hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(viewer: Zoooom, options?: JoystickOptions) {\n this.viewer = viewer;\n this.options = {\n radius: options?.radius ?? JOYSTICK_RADIUS,\n deadzone: options?.deadzone ?? JOYSTICK_DEADZONE,\n maxSpeed: options?.maxSpeed ?? MAX_JOYSTICK_SPEED,\n position: options?.position ?? 'bottom-center',\n showToggle: options?.showToggle ?? true,\n dwellTimeout: options?.dwellTimeout ?? DWELL_TIMEOUT,\n };\n\n injectJoystickStyles();\n\n const elements = this.viewer.getElements();\n this.dom = createJoystickDOM(elements.container);\n this.bindEvents();\n }\n\n show(): void {\n this.visible = true;\n this.dom.wrap.classList.add('visible');\n this.dom.wrap.setAttribute('aria-hidden', 'false');\n this.dom.toggle.setAttribute('aria-expanded', 'true');\n if (this.hideTimer) clearTimeout(this.hideTimer);\n }\n\n hide(): void {\n this.visible = false;\n this.dom.wrap.classList.remove('visible');\n this.dom.wrap.setAttribute('aria-hidden', 'true');\n this.dom.toggle.setAttribute('aria-expanded', 'false');\n this.stopMovement();\n this.clearDirection();\n }\n\n destroy(): void {\n this.hide();\n this.stopMovement();\n if (this.dwellTimer) clearTimeout(this.dwellTimer);\n if (this.hideTimer) clearTimeout(this.hideTimer);\n destroyJoystickDOM(this.dom);\n }\n\n private bindEvents(): void {\n const { toggle, disc, zoomIn, zoomOut, innerCircle } = this.dom;\n\n // Toggle button\n toggle.addEventListener('click', () => {\n if (this.visible) this.hide();\n else this.show();\n });\n\n toggle.addEventListener('mouseenter', () => this.show());\n toggle.addEventListener('mouseleave', () => {\n this.hideTimer = setTimeout(() => this.hide(), 15000);\n });\n\n // Disc — panning\n disc.addEventListener('mousemove', (e) => {\n if (e.target !== disc) return;\n if (!this.isDwelling) {\n this.startDwell(e);\n } else {\n this.handleMove(e);\n }\n });\n\n disc.addEventListener('mousedown', (e) => {\n if (e.target !== disc) return;\n e.preventDefault();\n this.handleMove(e);\n\n const moveHandler = (me: MouseEvent) => this.handleMove(me);\n document.addEventListener('mousemove', moveHandler);\n document.addEventListener('mouseup', () => {\n document.removeEventListener('mousemove', moveHandler);\n this.stopDwell();\n this.resetJoystick();\n }, { once: true });\n });\n\n disc.addEventListener('mouseleave', () => {\n this.stopDwell();\n this.resetJoystick();\n });\n\n // Touch on disc\n disc.addEventListener('touchstart', (e) => {\n if (e.target !== disc) return;\n e.preventDefault();\n this.handleMove(e);\n\n const moveHandler = (te: TouchEvent) => this.handleMove(te);\n document.addEventListener('touchmove', moveHandler, { passive: false });\n document.addEventListener('touchend', () => {\n document.removeEventListener('touchmove', moveHandler);\n this.stopDwell();\n this.resetJoystick();\n }, { once: true });\n }, { passive: false });\n\n // Zoom buttons\n zoomIn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.viewer.zoomIn();\n });\n\n zoomOut.addEventListener('click', (e) => {\n e.stopPropagation();\n this.viewer.zoomOut();\n });\n\n // Stop panning when entering inner circle\n innerCircle.addEventListener('mouseenter', () => {\n this.stopDwell();\n this.resetJoystick();\n });\n\n innerCircle.addEventListener('mousedown', (e) => e.stopPropagation());\n innerCircle.addEventListener('touchstart', (e) => e.stopPropagation(), { passive: false });\n }\n\n private handleMove(event: MouseEvent | TouchEvent): void {\n if (!this.visible) return;\n\n const clientX = 'clientX' in event ? event.clientX : event.touches[0]?.clientX ?? 0;\n const clientY = 'clientY' in event ? event.clientY : event.touches[0]?.clientY ?? 0;\n\n const rect = this.dom.disc.getBoundingClientRect();\n const centerX = rect.left + rect.width / 2;\n const centerY = rect.top + rect.height / 2;\n const distX = clientX - centerX;\n const distY = clientY - centerY;\n const distance = Math.sqrt(distX * distX + distY * distY);\n\n // Normalize to -1..1\n let normalizedX = distX / this.options.radius;\n let normalizedY = distY / this.options.radius;\n\n if (distance > this.options.radius) {\n normalizedX = normalizedX * (this.options.radius / distance);\n normalizedY = normalizedY * (this.options.radius / distance);\n }\n\n if (Math.abs(normalizedX) < this.options.deadzone) normalizedX = 0;\n if (Math.abs(normalizedY) < this.options.deadzone) normalizedY = 0;\n\n this.joystickX = normalizedX;\n this.joystickY = normalizedY;\n\n // Direction feedback\n if (distance > this.options.radius * this.options.deadzone) {\n const angle = Math.atan2(distY, distX) * 180 / Math.PI;\n const dir = angleToDirection(angle);\n if (dir !== this.currentDirection) {\n this.clearDirection();\n this.dom.disc.classList.add(dir);\n this.currentDirection = dir;\n }\n } else {\n this.clearDirection();\n }\n\n // Start movement if not already running\n if (!this.animationId && (Math.abs(normalizedX) > this.options.deadzone || Math.abs(normalizedY) > this.options.deadzone)) {\n this.active = true;\n this.dom.disc.classList.add('active');\n this.startMovement();\n this.updateAria(normalizedX, normalizedY);\n } else if (Math.abs(normalizedX) <= this.options.deadzone && Math.abs(normalizedY) <= this.options.deadzone) {\n this.active = false;\n this.dom.disc.classList.remove('active');\n this.stopMovement();\n this.dom.disc.setAttribute('aria-valuenow', '0');\n this.dom.disc.setAttribute('aria-valuetext', 'Center position — not moving');\n }\n }\n\n private startDwell(e: MouseEvent | TouchEvent): void {\n if (this.dwellTimer) clearTimeout(this.dwellTimer);\n this.dwellTimer = setTimeout(() => {\n this.isDwelling = true;\n this.handleMove(e);\n }, this.options.dwellTimeout);\n }\n\n private stopDwell(): void {\n if (this.dwellTimer) {\n clearTimeout(this.dwellTimer);\n this.dwellTimer = null;\n }\n this.isDwelling = false;\n }\n\n private startMovement(): void {\n if (this.animationId) return;\n const step = () => {\n if (!this.active) { this.stopMovement(); return; }\n const vx = -this.joystickX * this.options.maxSpeed;\n const vy = -this.joystickY * this.options.maxSpeed;\n this.viewer.applyVelocity(vx, vy);\n this.animationId = requestAnimationFrame(step);\n };\n this.animationId = requestAnimationFrame(step);\n }\n\n private stopMovement(): void {\n if (this.animationId) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n }\n\n private resetJoystick(): void {\n this.joystickX = 0;\n this.joystickY = 0;\n this.active = false;\n this.stopMovement();\n this.clearDirection();\n this.dom.disc.classList.remove('active');\n }\n\n private clearDirection(): void {\n if (this.currentDirection) {\n this.dom.disc.classList.remove(this.currentDirection);\n this.currentDirection = '';\n }\n }\n\n private updateAria(x: number, y: number): void {\n const magnitude = Math.sqrt(x * x + y * y);\n this.dom.disc.setAttribute('aria-valuenow', magnitude.toFixed(2));\n\n let direction: string;\n if (Math.abs(x) > Math.abs(y)) {\n direction = x > 0 ? 'right' : 'left';\n } else {\n direction = y > 0 ? 'down' : 'up';\n }\n\n const intensity = magnitude > 0.7 ? 'fast' : magnitude > 0.3 ? 'medium' : 'slow';\n this.dom.disc.setAttribute('aria-valuetext', `Moving ${intensity} ${direction}`);\n }\n}\n"]}
@@ -0,0 +1,31 @@
1
+ import { Z as Zoooom, J as JoystickOptions } from './Zoooom-BypxEt9q.cjs';
2
+
3
+ declare class ZoooomJoystick {
4
+ private viewer;
5
+ private dom;
6
+ private options;
7
+ private visible;
8
+ private active;
9
+ private animationId;
10
+ private joystickX;
11
+ private joystickY;
12
+ private currentDirection;
13
+ private dwellTimer;
14
+ private isDwelling;
15
+ private hideTimer;
16
+ constructor(viewer: Zoooom, options?: JoystickOptions);
17
+ show(): void;
18
+ hide(): void;
19
+ destroy(): void;
20
+ private bindEvents;
21
+ private handleMove;
22
+ private startDwell;
23
+ private stopDwell;
24
+ private startMovement;
25
+ private stopMovement;
26
+ private resetJoystick;
27
+ private clearDirection;
28
+ private updateAria;
29
+ }
30
+
31
+ export { JoystickOptions, ZoooomJoystick };
@@ -0,0 +1,31 @@
1
+ import { Z as Zoooom, J as JoystickOptions } from './Zoooom-BypxEt9q.js';
2
+
3
+ declare class ZoooomJoystick {
4
+ private viewer;
5
+ private dom;
6
+ private options;
7
+ private visible;
8
+ private active;
9
+ private animationId;
10
+ private joystickX;
11
+ private joystickY;
12
+ private currentDirection;
13
+ private dwellTimer;
14
+ private isDwelling;
15
+ private hideTimer;
16
+ constructor(viewer: Zoooom, options?: JoystickOptions);
17
+ show(): void;
18
+ hide(): void;
19
+ destroy(): void;
20
+ private bindEvents;
21
+ private handleMove;
22
+ private startDwell;
23
+ private stopDwell;
24
+ private startMovement;
25
+ private stopMovement;
26
+ private resetJoystick;
27
+ private clearDirection;
28
+ private updateAria;
29
+ }
30
+
31
+ export { JoystickOptions, ZoooomJoystick };
@@ -0,0 +1,502 @@
1
+ // src/core/constants.ts
2
+ var JOYSTICK_RADIUS = 60;
3
+ var JOYSTICK_DEADZONE = 0.1;
4
+ var MAX_JOYSTICK_SPEED = 10;
5
+ var DWELL_TIMEOUT = 100;
6
+
7
+ // src/joystick/dom.ts
8
+ function createJoystickDOM(container) {
9
+ const toggle = document.createElement("button");
10
+ toggle.className = "zoooom-joystick-toggle";
11
+ toggle.setAttribute("aria-label", "Toggle navigation joystick");
12
+ toggle.setAttribute("aria-expanded", "false");
13
+ toggle.textContent = "\u2316";
14
+ container.appendChild(toggle);
15
+ const wrap = document.createElement("div");
16
+ wrap.className = "zoooom-joystick-wrap";
17
+ wrap.setAttribute("aria-hidden", "true");
18
+ const disc = document.createElement("div");
19
+ disc.className = "zoooom-disc";
20
+ disc.setAttribute("role", "slider");
21
+ disc.setAttribute("aria-label", "Pan navigation control");
22
+ disc.setAttribute("aria-valuenow", "0");
23
+ disc.setAttribute("aria-valuemin", "0");
24
+ disc.setAttribute("aria-valuemax", "1");
25
+ disc.setAttribute("aria-valuetext", "Center position \u2014 not moving");
26
+ disc.setAttribute("tabindex", "0");
27
+ const innerCircle = document.createElement("div");
28
+ innerCircle.className = "zoooom-inner-circle";
29
+ const zoomOut = document.createElement("div");
30
+ zoomOut.className = "zoooom-zoom-half zoooom-zoom-out";
31
+ zoomOut.setAttribute("role", "button");
32
+ zoomOut.setAttribute("aria-label", "Zoom out");
33
+ zoomOut.setAttribute("tabindex", "0");
34
+ zoomOut.textContent = "\u2212";
35
+ const zoomIn = document.createElement("div");
36
+ zoomIn.className = "zoooom-zoom-half zoooom-zoom-in";
37
+ zoomIn.setAttribute("role", "button");
38
+ zoomIn.setAttribute("aria-label", "Zoom in");
39
+ zoomIn.setAttribute("tabindex", "0");
40
+ zoomIn.textContent = "+";
41
+ innerCircle.appendChild(zoomOut);
42
+ innerCircle.appendChild(zoomIn);
43
+ const arrows = document.createElement("div");
44
+ arrows.className = "zoooom-arrows";
45
+ arrows.setAttribute("aria-hidden", "true");
46
+ for (const dir of ["n", "e", "s", "w"]) {
47
+ const arrow = document.createElement("div");
48
+ arrow.className = `zoooom-arrow zoooom-arrow-${dir}`;
49
+ arrows.appendChild(arrow);
50
+ }
51
+ disc.appendChild(innerCircle);
52
+ disc.appendChild(arrows);
53
+ wrap.appendChild(disc);
54
+ container.appendChild(wrap);
55
+ return { wrap, toggle, disc, innerCircle, zoomIn, zoomOut };
56
+ }
57
+ function destroyJoystickDOM(dom) {
58
+ dom.wrap.remove();
59
+ dom.toggle.remove();
60
+ }
61
+
62
+ // src/styles/joystick.ts
63
+ var JOYSTICK_CSS = `
64
+ .zoooom-joystick-wrap {
65
+ position: fixed;
66
+ bottom: 20px;
67
+ left: 50%;
68
+ transform: translateX(-50%);
69
+ z-index: 100;
70
+ touch-action: none;
71
+ opacity: 0;
72
+ pointer-events: none;
73
+ transition: opacity 0.3s ease-out, transform 0.3s ease-out;
74
+ }
75
+
76
+ .zoooom-joystick-wrap.visible {
77
+ opacity: 1;
78
+ pointer-events: auto;
79
+ }
80
+
81
+ .zoooom-joystick-toggle {
82
+ position: fixed;
83
+ bottom: 20px;
84
+ left: 50%;
85
+ transform: translateX(-50%);
86
+ width: 56px;
87
+ height: 56px;
88
+ border-radius: 50%;
89
+ background: rgba(0, 0, 0, 0.5);
90
+ border: 2px solid rgba(255, 255, 255, 0.6);
91
+ cursor: pointer;
92
+ z-index: 99;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ color: #fff;
97
+ font-size: 20px;
98
+ font-weight: bold;
99
+ backdrop-filter: blur(4px);
100
+ transition: background 0.2s, box-shadow 0.2s;
101
+ }
102
+
103
+ .zoooom-joystick-toggle:hover {
104
+ background: rgba(0, 0, 0, 0.7);
105
+ box-shadow: 0 0 12px rgba(0, 0, 0, 0.4);
106
+ }
107
+
108
+ .zoooom-joystick-toggle:focus-visible {
109
+ outline: 2px solid #2196f3;
110
+ outline-offset: 2px;
111
+ }
112
+
113
+ .zoooom-disc {
114
+ width: 200px;
115
+ height: 200px;
116
+ border-radius: 50%;
117
+ background: rgba(0, 0, 0, 0.4);
118
+ border: 2px solid rgba(255, 255, 255, 0.6);
119
+ position: relative;
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ touch-action: none;
124
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
125
+ }
126
+
127
+ .zoooom-disc.active {
128
+ border-color: rgba(255, 255, 255, 0.9);
129
+ }
130
+
131
+ .zoooom-inner-circle {
132
+ width: 72px;
133
+ height: 72px;
134
+ border-radius: 50%;
135
+ background: rgba(255, 255, 255, 0.15);
136
+ border: 1px solid rgba(255, 255, 255, 0.5);
137
+ display: flex;
138
+ position: relative;
139
+ z-index: 3;
140
+ }
141
+
142
+ .zoooom-zoom-half {
143
+ width: 50%;
144
+ height: 100%;
145
+ display: flex;
146
+ align-items: center;
147
+ justify-content: center;
148
+ cursor: pointer;
149
+ font-weight: bold;
150
+ font-size: 22px;
151
+ color: #fff;
152
+ user-select: none;
153
+ transition: background 0.15s;
154
+ }
155
+
156
+ .zoooom-zoom-half:hover {
157
+ background: rgba(255, 255, 255, 0.25);
158
+ }
159
+
160
+ .zoooom-zoom-out {
161
+ border-radius: 36px 0 0 36px;
162
+ border-right: 1px solid rgba(255, 255, 255, 0.4);
163
+ }
164
+
165
+ .zoooom-zoom-in {
166
+ border-radius: 0 36px 36px 0;
167
+ }
168
+
169
+ .zoooom-arrows {
170
+ position: absolute;
171
+ width: 100%;
172
+ height: 100%;
173
+ border-radius: 50%;
174
+ pointer-events: none;
175
+ overflow: hidden;
176
+ }
177
+
178
+ .zoooom-arrow {
179
+ position: absolute;
180
+ width: 0;
181
+ height: 0;
182
+ opacity: 0;
183
+ transition: opacity 0.2s;
184
+ }
185
+
186
+ .zoooom-arrow-n {
187
+ top: 14px;
188
+ left: 50%;
189
+ transform: translateX(-50%);
190
+ border-left: 10px solid transparent;
191
+ border-right: 10px solid transparent;
192
+ border-bottom: 14px solid rgba(255, 255, 255, 0.7);
193
+ }
194
+
195
+ .zoooom-arrow-e {
196
+ top: 50%;
197
+ right: 14px;
198
+ transform: translateY(-50%);
199
+ border-top: 10px solid transparent;
200
+ border-bottom: 10px solid transparent;
201
+ border-left: 14px solid rgba(255, 255, 255, 0.7);
202
+ }
203
+
204
+ .zoooom-arrow-s {
205
+ bottom: 14px;
206
+ left: 50%;
207
+ transform: translateX(-50%);
208
+ border-left: 10px solid transparent;
209
+ border-right: 10px solid transparent;
210
+ border-top: 14px solid rgba(255, 255, 255, 0.7);
211
+ }
212
+
213
+ .zoooom-arrow-w {
214
+ top: 50%;
215
+ left: 14px;
216
+ transform: translateY(-50%);
217
+ border-top: 10px solid transparent;
218
+ border-bottom: 10px solid transparent;
219
+ border-right: 14px solid rgba(255, 255, 255, 0.7);
220
+ }
221
+
222
+ .zoooom-disc.north .zoooom-arrow-n,
223
+ .zoooom-disc.south .zoooom-arrow-s,
224
+ .zoooom-disc.east .zoooom-arrow-e,
225
+ .zoooom-disc.west .zoooom-arrow-w,
226
+ .zoooom-disc.north-east .zoooom-arrow-n,
227
+ .zoooom-disc.north-east .zoooom-arrow-e,
228
+ .zoooom-disc.south-east .zoooom-arrow-s,
229
+ .zoooom-disc.south-east .zoooom-arrow-e,
230
+ .zoooom-disc.south-west .zoooom-arrow-s,
231
+ .zoooom-disc.south-west .zoooom-arrow-w,
232
+ .zoooom-disc.north-west .zoooom-arrow-n,
233
+ .zoooom-disc.north-west .zoooom-arrow-w {
234
+ opacity: 1;
235
+ }
236
+
237
+ @media (max-width: 768px) {
238
+ .zoooom-disc {
239
+ width: 140px;
240
+ height: 140px;
241
+ }
242
+
243
+ .zoooom-inner-circle {
244
+ width: 56px;
245
+ height: 56px;
246
+ }
247
+
248
+ .zoooom-joystick-toggle {
249
+ width: 48px;
250
+ height: 48px;
251
+ font-size: 16px;
252
+ }
253
+ }
254
+
255
+ @media (prefers-reduced-motion: reduce) {
256
+ .zoooom-joystick-wrap {
257
+ transition: none;
258
+ }
259
+
260
+ .zoooom-arrow {
261
+ transition: none;
262
+ }
263
+ }
264
+ `;
265
+ var injected = false;
266
+ function injectJoystickStyles() {
267
+ if (injected || typeof document === "undefined") return;
268
+ const style = document.createElement("style");
269
+ style.setAttribute("data-zoooom-joystick", "");
270
+ style.textContent = JOYSTICK_CSS;
271
+ document.head.appendChild(style);
272
+ injected = true;
273
+ }
274
+
275
+ // src/joystick/joystick.ts
276
+ function angleToDirection(angle) {
277
+ if (angle >= -22.5 && angle < 22.5) return "east";
278
+ if (angle >= 22.5 && angle < 67.5) return "south-east";
279
+ if (angle >= 67.5 && angle < 112.5) return "south";
280
+ if (angle >= 112.5 && angle < 157.5) return "south-west";
281
+ if (angle >= 157.5 || angle < -157.5) return "west";
282
+ if (angle >= -157.5 && angle < -112.5) return "north-west";
283
+ if (angle >= -112.5 && angle < -67.5) return "north";
284
+ return "north-east";
285
+ }
286
+ var ZoooomJoystick = class {
287
+ constructor(viewer, options) {
288
+ this.visible = false;
289
+ this.active = false;
290
+ this.animationId = null;
291
+ this.joystickX = 0;
292
+ this.joystickY = 0;
293
+ this.currentDirection = "";
294
+ this.dwellTimer = null;
295
+ this.isDwelling = false;
296
+ this.hideTimer = null;
297
+ this.viewer = viewer;
298
+ this.options = {
299
+ radius: options?.radius ?? JOYSTICK_RADIUS,
300
+ deadzone: options?.deadzone ?? JOYSTICK_DEADZONE,
301
+ maxSpeed: options?.maxSpeed ?? MAX_JOYSTICK_SPEED,
302
+ position: options?.position ?? "bottom-center",
303
+ showToggle: options?.showToggle ?? true,
304
+ dwellTimeout: options?.dwellTimeout ?? DWELL_TIMEOUT
305
+ };
306
+ injectJoystickStyles();
307
+ const elements = this.viewer.getElements();
308
+ this.dom = createJoystickDOM(elements.container);
309
+ this.bindEvents();
310
+ }
311
+ show() {
312
+ this.visible = true;
313
+ this.dom.wrap.classList.add("visible");
314
+ this.dom.wrap.setAttribute("aria-hidden", "false");
315
+ this.dom.toggle.setAttribute("aria-expanded", "true");
316
+ if (this.hideTimer) clearTimeout(this.hideTimer);
317
+ }
318
+ hide() {
319
+ this.visible = false;
320
+ this.dom.wrap.classList.remove("visible");
321
+ this.dom.wrap.setAttribute("aria-hidden", "true");
322
+ this.dom.toggle.setAttribute("aria-expanded", "false");
323
+ this.stopMovement();
324
+ this.clearDirection();
325
+ }
326
+ destroy() {
327
+ this.hide();
328
+ this.stopMovement();
329
+ if (this.dwellTimer) clearTimeout(this.dwellTimer);
330
+ if (this.hideTimer) clearTimeout(this.hideTimer);
331
+ destroyJoystickDOM(this.dom);
332
+ }
333
+ bindEvents() {
334
+ const { toggle, disc, zoomIn, zoomOut, innerCircle } = this.dom;
335
+ toggle.addEventListener("click", () => {
336
+ if (this.visible) this.hide();
337
+ else this.show();
338
+ });
339
+ toggle.addEventListener("mouseenter", () => this.show());
340
+ toggle.addEventListener("mouseleave", () => {
341
+ this.hideTimer = setTimeout(() => this.hide(), 15e3);
342
+ });
343
+ disc.addEventListener("mousemove", (e) => {
344
+ if (e.target !== disc) return;
345
+ if (!this.isDwelling) {
346
+ this.startDwell(e);
347
+ } else {
348
+ this.handleMove(e);
349
+ }
350
+ });
351
+ disc.addEventListener("mousedown", (e) => {
352
+ if (e.target !== disc) return;
353
+ e.preventDefault();
354
+ this.handleMove(e);
355
+ const moveHandler = (me) => this.handleMove(me);
356
+ document.addEventListener("mousemove", moveHandler);
357
+ document.addEventListener("mouseup", () => {
358
+ document.removeEventListener("mousemove", moveHandler);
359
+ this.stopDwell();
360
+ this.resetJoystick();
361
+ }, { once: true });
362
+ });
363
+ disc.addEventListener("mouseleave", () => {
364
+ this.stopDwell();
365
+ this.resetJoystick();
366
+ });
367
+ disc.addEventListener("touchstart", (e) => {
368
+ if (e.target !== disc) return;
369
+ e.preventDefault();
370
+ this.handleMove(e);
371
+ const moveHandler = (te) => this.handleMove(te);
372
+ document.addEventListener("touchmove", moveHandler, { passive: false });
373
+ document.addEventListener("touchend", () => {
374
+ document.removeEventListener("touchmove", moveHandler);
375
+ this.stopDwell();
376
+ this.resetJoystick();
377
+ }, { once: true });
378
+ }, { passive: false });
379
+ zoomIn.addEventListener("click", (e) => {
380
+ e.stopPropagation();
381
+ this.viewer.zoomIn();
382
+ });
383
+ zoomOut.addEventListener("click", (e) => {
384
+ e.stopPropagation();
385
+ this.viewer.zoomOut();
386
+ });
387
+ innerCircle.addEventListener("mouseenter", () => {
388
+ this.stopDwell();
389
+ this.resetJoystick();
390
+ });
391
+ innerCircle.addEventListener("mousedown", (e) => e.stopPropagation());
392
+ innerCircle.addEventListener("touchstart", (e) => e.stopPropagation(), { passive: false });
393
+ }
394
+ handleMove(event) {
395
+ if (!this.visible) return;
396
+ const clientX = "clientX" in event ? event.clientX : event.touches[0]?.clientX ?? 0;
397
+ const clientY = "clientY" in event ? event.clientY : event.touches[0]?.clientY ?? 0;
398
+ const rect = this.dom.disc.getBoundingClientRect();
399
+ const centerX = rect.left + rect.width / 2;
400
+ const centerY = rect.top + rect.height / 2;
401
+ const distX = clientX - centerX;
402
+ const distY = clientY - centerY;
403
+ const distance = Math.sqrt(distX * distX + distY * distY);
404
+ let normalizedX = distX / this.options.radius;
405
+ let normalizedY = distY / this.options.radius;
406
+ if (distance > this.options.radius) {
407
+ normalizedX = normalizedX * (this.options.radius / distance);
408
+ normalizedY = normalizedY * (this.options.radius / distance);
409
+ }
410
+ if (Math.abs(normalizedX) < this.options.deadzone) normalizedX = 0;
411
+ if (Math.abs(normalizedY) < this.options.deadzone) normalizedY = 0;
412
+ this.joystickX = normalizedX;
413
+ this.joystickY = normalizedY;
414
+ if (distance > this.options.radius * this.options.deadzone) {
415
+ const angle = Math.atan2(distY, distX) * 180 / Math.PI;
416
+ const dir = angleToDirection(angle);
417
+ if (dir !== this.currentDirection) {
418
+ this.clearDirection();
419
+ this.dom.disc.classList.add(dir);
420
+ this.currentDirection = dir;
421
+ }
422
+ } else {
423
+ this.clearDirection();
424
+ }
425
+ if (!this.animationId && (Math.abs(normalizedX) > this.options.deadzone || Math.abs(normalizedY) > this.options.deadzone)) {
426
+ this.active = true;
427
+ this.dom.disc.classList.add("active");
428
+ this.startMovement();
429
+ this.updateAria(normalizedX, normalizedY);
430
+ } else if (Math.abs(normalizedX) <= this.options.deadzone && Math.abs(normalizedY) <= this.options.deadzone) {
431
+ this.active = false;
432
+ this.dom.disc.classList.remove("active");
433
+ this.stopMovement();
434
+ this.dom.disc.setAttribute("aria-valuenow", "0");
435
+ this.dom.disc.setAttribute("aria-valuetext", "Center position \u2014 not moving");
436
+ }
437
+ }
438
+ startDwell(e) {
439
+ if (this.dwellTimer) clearTimeout(this.dwellTimer);
440
+ this.dwellTimer = setTimeout(() => {
441
+ this.isDwelling = true;
442
+ this.handleMove(e);
443
+ }, this.options.dwellTimeout);
444
+ }
445
+ stopDwell() {
446
+ if (this.dwellTimer) {
447
+ clearTimeout(this.dwellTimer);
448
+ this.dwellTimer = null;
449
+ }
450
+ this.isDwelling = false;
451
+ }
452
+ startMovement() {
453
+ if (this.animationId) return;
454
+ const step = () => {
455
+ if (!this.active) {
456
+ this.stopMovement();
457
+ return;
458
+ }
459
+ const vx = -this.joystickX * this.options.maxSpeed;
460
+ const vy = -this.joystickY * this.options.maxSpeed;
461
+ this.viewer.applyVelocity(vx, vy);
462
+ this.animationId = requestAnimationFrame(step);
463
+ };
464
+ this.animationId = requestAnimationFrame(step);
465
+ }
466
+ stopMovement() {
467
+ if (this.animationId) {
468
+ cancelAnimationFrame(this.animationId);
469
+ this.animationId = null;
470
+ }
471
+ }
472
+ resetJoystick() {
473
+ this.joystickX = 0;
474
+ this.joystickY = 0;
475
+ this.active = false;
476
+ this.stopMovement();
477
+ this.clearDirection();
478
+ this.dom.disc.classList.remove("active");
479
+ }
480
+ clearDirection() {
481
+ if (this.currentDirection) {
482
+ this.dom.disc.classList.remove(this.currentDirection);
483
+ this.currentDirection = "";
484
+ }
485
+ }
486
+ updateAria(x, y) {
487
+ const magnitude = Math.sqrt(x * x + y * y);
488
+ this.dom.disc.setAttribute("aria-valuenow", magnitude.toFixed(2));
489
+ let direction;
490
+ if (Math.abs(x) > Math.abs(y)) {
491
+ direction = x > 0 ? "right" : "left";
492
+ } else {
493
+ direction = y > 0 ? "down" : "up";
494
+ }
495
+ const intensity = magnitude > 0.7 ? "fast" : magnitude > 0.3 ? "medium" : "slow";
496
+ this.dom.disc.setAttribute("aria-valuetext", `Moving ${intensity} ${direction}`);
497
+ }
498
+ };
499
+
500
+ export { ZoooomJoystick };
501
+ //# sourceMappingURL=joystick.js.map
502
+ //# sourceMappingURL=joystick.js.map