diff options
Diffstat (limited to 'public/app.js')
| -rw-r--r-- | public/app.js | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/public/app.js b/public/app.js index 9f27b87..aa2eef3 100644 --- a/public/app.js +++ b/public/app.js @@ -191,6 +191,7 @@ function setCurrent(id, rect) { tiles.get(id).el.classList.add("current") if (!userZoomed) scale = worldScale() center() + renderDropzones(id) getExits(id) } @@ -211,8 +212,8 @@ function renderNav(id) { b.innerHTML = ARROW_SVG[ex.dir] b.addEventListener("pointerdown", (e) => e.stopPropagation()) b.addEventListener("click", (e) => { e.stopPropagation(); moveFrom(id, ex.dir) }) - zone.addEventListener("pointerenter", () => showGhost(choosePlacement(id, ex.dir))) - zone.addEventListener("pointerleave", () => hideGhost()) + b.addEventListener("pointerenter", () => showGhost(choosePlacement(id, ex.dir))) + b.addEventListener("pointerleave", () => hideGhost()) zone.appendChild(b) nav.appendChild(zone) } @@ -232,6 +233,7 @@ async function getExits(id) { const exits = data.exits || [] exitsCache.set(id, exits) renderNav(id) + if (cur && cur.id === id) renderDropzones(id) return exits } catch { return null @@ -309,6 +311,34 @@ function hideGhost() { } } +let dropzones = [] +function clearDropzones() { + for (const z of dropzones) world.removeChild(z) + dropzones = [] +} + +function renderDropzones(id) { + clearDropzones() + const t = tiles.get(id) + if (!t) return + for (const dir of ["N", "E", "S", "W"]) { + const p = choosePlacement(id, dir) + if (!p) continue + const z = document.createElement("div") + z.className = "dropzone" + z.style.left = p.rect.x + "px" + z.style.top = p.rect.y + "px" + z.style.width = p.rect.w + "px" + z.style.height = p.rect.h + "px" + z.addEventListener("pointerenter", () => showGhost(p)) + z.addEventListener("pointerleave", () => hideGhost()) + z.addEventListener("pointerdown", (e) => e.stopPropagation()) + z.addEventListener("click", () => moveFrom(id, dir)) + world.appendChild(z) + dropzones.push(z) + } +} + stage.addEventListener("pointerover", (e) => { const tileEl = e.target.closest(".tile") if (tileEl) getExits(Number(tileEl.dataset.id)) @@ -350,15 +380,19 @@ stage.addEventListener("pointerup", (e) => { let zoomTimer = 0 stage.addEventListener("wheel", (e) => { e.preventDefault() - const rect = stage.getBoundingClientRect() - const mx = e.clientX - rect.left - const my = e.clientY - rect.top + let dx = e.deltaX let dy = e.deltaY - if (e.deltaMode === 1) dy *= 16 - else if (e.deltaMode === 2) dy *= window.innerHeight - const factor = Math.exp(-dy * (e.ctrlKey ? 0.012 : 0.0018)) + if (e.deltaMode === 1) { dx *= 16; dy *= 16 } + else if (e.deltaMode === 2) { dx *= window.innerWidth; dy *= window.innerHeight } world.style.transition = "none" - zoomAt(mx, my, factor) + if (e.ctrlKey) { + const rect = stage.getBoundingClientRect() + zoomAt(e.clientX - rect.left, e.clientY - rect.top, Math.exp(-dy * 0.01)) + } else { + panX -= dx + panY -= dy + applyPan() + } clearTimeout(zoomTimer) zoomTimer = setTimeout(() => { world.style.transition = "" }, 120) }, { passive: false }) |
