aboutsummaryrefslogtreecommitdiff
path: root/public/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'public/app.js')
-rw-r--r--public/app.js77
1 files changed, 47 insertions, 30 deletions
diff --git a/public/app.js b/public/app.js
index cce9bc8..11f19b9 100644
--- a/public/app.js
+++ b/public/app.js
@@ -348,8 +348,8 @@ let ghostVisible = false
function setPreviewHidden(hidden) {
ghostVisible = hidden
if (!cur) return
- const zs = zones.get(cur.id)
- if (zs) for (const z of zs) z.classList.toggle("hidden", hidden)
+ const entry = zones.get(cur.id)
+ if (entry) for (const z of entry.els) z.classList.toggle("hidden", hidden)
}
function showGhost(p) {
if (!p) return
@@ -392,9 +392,9 @@ function cancelHideGhost() {
const zones = new Map()
function clearTileZones(id) {
- const zs = zones.get(id)
- if (zs) {
- for (const z of zs) world.removeChild(z)
+ const entry = zones.get(id)
+ if (entry) {
+ for (const z of entry.els) world.removeChild(z)
zones.delete(id)
}
}
@@ -408,42 +408,59 @@ function renderTileZones(id) {
if (!tiles.has(id) || !exitsCache.has(id)) return
const cx = (window.innerWidth / 2 - panX) / scale
const cy = (window.innerHeight / 2 - panY) / scale
- let bestDir = null
- let best = null
- let bestD = Infinity
+ const dirs = []
for (const dir of ["N", "E", "S", "W"]) {
if (adjacentTile(id, dir)) continue
const p = choosePlacement(id, dir)
if (!p) continue
const d = Math.hypot(p.rect.x + p.rect.w / 2 - cx, p.rect.y + p.rect.h / 2 - cy)
- if (d < bestD) { bestD = d; bestDir = dir; best = p }
+ dirs.push({ dir, p, d })
+ }
+ const key = dirs.map((x) => x.dir + x.p.info.id + "@" + x.p.rect.x + "," + x.p.rect.y).join("|")
+ let best = null
+ for (const x of dirs) if (!best || x.d < best.d) best = x
+ const entry = zones.get(id)
+ if (entry && entry.key === key) {
+ if (best && best.dir !== entry.bestDir) {
+ const z = entry.els.find((el) => el.dataset.dir === best.dir)
+ if (z) {
+ z.appendChild(entry.prevEl)
+ entry.img.src = best.p.info.thumb
+ entry.bestDir = best.dir
+ }
+ }
+ return
}
- const existing = zones.get(id) && zones.get(id)[0]
- if (best && existing &&
- existing.dataset.dir === bestDir &&
- existing.dataset.key === best.info.id + "|" + best.rect.x + "," + best.rect.y) return
clearTileZones(id)
if (!best) return
- const z = document.createElement("div")
- z.className = "dropzone"
- z.dataset.dir = bestDir
- z.dataset.key = best.info.id + "|" + best.rect.x + "," + best.rect.y
- z.style.left = best.rect.x + "px"
- z.style.top = best.rect.y + "px"
- z.style.width = best.rect.w + "px"
- z.style.height = best.rect.h + "px"
- const prev = document.createElement("div")
- prev.className = "preview"
+ const els = []
+ const prevEl = document.createElement("div")
+ prevEl.className = "preview"
const img = document.createElement("img")
- img.src = best.info.thumb
+ img.src = best.p.info.thumb
img.alt = ""
img.loading = "lazy"
- prev.appendChild(img)
- z.appendChild(prev)
- z.addEventListener("pointerdown", (e) => e.stopPropagation())
- z.addEventListener("click", () => traverseFrom(id, bestDir))
- world.appendChild(z)
- zones.set(id, [z])
+ prevEl.appendChild(img)
+ for (const x of dirs) {
+ const z = document.createElement("div")
+ z.className = "dropzone"
+ z.dataset.dir = x.dir
+ z.style.left = x.p.rect.x + "px"
+ z.style.top = x.p.rect.y + "px"
+ z.style.width = x.p.rect.w + "px"
+ z.style.height = x.p.rect.h + "px"
+ z.addEventListener("pointerdown", (e) => e.stopPropagation())
+ z.addEventListener("click", () => traverseFrom(id, x.dir))
+ if (!TOUCH && x.dir !== best.dir) {
+ z.addEventListener("pointermove", () => { cancelHideGhost(); showGhost(x.p) })
+ z.addEventListener("pointerleave", () => scheduleHideGhost())
+ }
+ world.appendChild(z)
+ els.push(z)
+ }
+ const bestEl = els.find((el) => el.dataset.dir === best.dir)
+ bestEl.appendChild(prevEl)
+ zones.set(id, { els, key, bestDir: best.dir, prevEl, img })
setPreviewHidden(ghostVisible)
}