diff options
Diffstat (limited to 'public')
| -rw-r--r-- | public/app.css | 16 | ||||
| -rw-r--r-- | public/app.js | 37 | ||||
| -rw-r--r-- | public/index.html | 4 |
3 files changed, 51 insertions, 6 deletions
diff --git a/public/app.css b/public/app.css index fd7612e..1e51b9b 100644 --- a/public/app.css +++ b/public/app.css @@ -58,6 +58,7 @@ html, body { transition: opacity .15s; } .preview.hot { opacity: .85; } +.preview.hidden { visibility: hidden; } .preview img { width: 100%; height: 100%; @@ -65,6 +66,21 @@ html, body { display: block; border-radius: 6px; } +.preview.loading img { visibility: hidden; } +.preview .spinner { + position: absolute; + inset: 0; + margin: auto; + width: 28px; + height: 28px; + border: 3px solid rgba(255, 255, 255, .25); + border-top-color: rgba(125, 211, 252, .9); + border-radius: 50%; + animation: spin .8s linear infinite; + display: none; +} +.preview.slow .spinner { display: block; } +@keyframes spin { to { transform: rotate(360deg); } } @keyframes lock { 0% { transform: scale(.2); opacity: 0; } diff --git a/public/app.js b/public/app.js index f323b22..4a55cb9 100644 --- a/public/app.js +++ b/public/app.js @@ -34,6 +34,7 @@ let panY = 0 let scale = 1 let userZoomed = false let drag = null +let previewsShown = false const TOUCH = typeof window.matchMedia === "function" && window.matchMedia("(hover: none)").matches @@ -323,6 +324,7 @@ function adjacentTile(id, dir) { } function traverseFrom(id, dir) { + previewsShown = false followEnabled = false const back = adjacentTile(id, dir) if (back) { @@ -377,18 +379,40 @@ function renderTileZones(id) { if (!best) return const els = [] const preview = document.createElement("div") - preview.className = "preview" + preview.className = "preview hidden" const previewImg = document.createElement("img") previewImg.alt = "" - previewImg.loading = "lazy" preview.appendChild(previewImg) + const spinner = document.createElement("div") + spinner.className = "spinner" + preview.appendChild(spinner) let hotDir = null + let loadTimer = 0 + const doneLoading = () => { + clearTimeout(loadTimer) + preview.classList.remove("loading", "slow") + } + previewImg.onload = doneLoading + previewImg.onerror = doneLoading const showAt = (x) => { + previewsShown = true + preview.classList.remove("hidden") preview.style.left = x.p.rect.x + "px" preview.style.top = x.p.rect.y + "px" preview.style.width = x.p.rect.w + "px" preview.style.height = x.p.rect.h + "px" - previewImg.src = x.p.info.thumb + const next = new URL(x.p.info.thumb, location.href).href + if (previewImg.src === next && previewImg.complete) { + doneLoading() + return + } + clearTimeout(loadTimer) + preview.classList.add("loading") + preview.classList.remove("slow") + previewImg.src = next + loadTimer = setTimeout(() => { + if (preview.classList.contains("loading")) preview.classList.add("slow") + }, 1000) } const reset = () => { hotDir = null @@ -424,7 +448,7 @@ function renderTileZones(id) { els.push(z) } world.appendChild(preview) - showAt(best) + if (previewsShown && best) showAt(best) zones.set(id, { els, key, preview, reset }) } @@ -496,6 +520,10 @@ stage.addEventListener("pointerdown", (e) => { }) stage.addEventListener("pointermove", (e) => { + if (!previewsShown) { + const entry = zones.get(cur && cur.id) + if (entry && entry.reset) entry.reset() + } if (pointers.has(e.pointerId)) { pointers.set(e.pointerId, { x: e.clientX, y: e.clientY }) if (pointers.size === 2 && pinchDist > 0) { @@ -541,6 +569,7 @@ stage.addEventListener("pointerup", (e) => { const id = Number(tile.dataset.id) followEnabled = false if (cur && cur.id === id) return + previewsShown = false setCurrent(id, tiles.get(id).rect) }) diff --git a/public/index.html b/public/index.html index b31e8ce..9475e4e 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="color-scheme" content="dark"> <title>pathways</title> - <link rel="stylesheet" href="/app.css?v=52"> + <link rel="stylesheet" href="/app.css?v=56"> </head> <body> <main id="stage"> @@ -29,6 +29,6 @@ <span id="progress-text"></span> </div> <div id="toast" role="status" aria-live="polite"></div> - <script src="/app.js?v=52"></script> + <script src="/app.js?v=56"></script> </body> </html> |
