From eca474fc85ba0c3ed15ca45f812ed444cf6a1a3d Mon Sep 17 00:00:00 2001 From: kanywst Date: Sat, 24 Oct 2026 23:32:40 +0900 Subject: [PATCH] perf(desk): stop restyling the whole desk on every camera frame The camera wrote --z onto #world each frame so the pile headings could scale with zoom. A custom property inherits, so every frame restyled the entire desk: 20 long tasks of ~80 ms during the intro and 880 ms of total blocking time on desktop. The few headings are now scaled directly, and only when the value changes. Desktop Lighthouse (devtools throttling) goes from 72 to 100, TBT to 0. --- src/scripts/desk.ts | 15 ++++++++++++++- src/styles/desk.css | 3 +-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/scripts/desk.ts b/src/scripts/desk.ts index 0b2572d..c61ad2b 100644 --- a/src/scripts/desk.ts +++ b/src/scripts/desk.ts @@ -6,6 +6,7 @@ const desk = document.getElementById("desk") as HTMLElement; const surface = document.querySelector(".surface") as HTMLElement; const world = document.getElementById("world") as HTMLElement; const items = [...world.querySelectorAll(".item")]; +const labelEls = items.filter((el) => el.classList.contains("label")); const zoomRead = document.querySelector(".zoom-read") as HTMLOutputElement; const minimap = document.querySelector(".minimap") as HTMLButtonElement; const modeToggle = document.querySelector("[data-mode-toggle]") as HTMLButtonElement; @@ -53,7 +54,9 @@ function unplace() { for (const el of items) { el.style.translate = ""; el.style.rotate = ""; + el.style.scale = ""; } + labelScale = 0; world.style.transform = ""; } @@ -163,7 +166,7 @@ function apply() { const tx = vw / 2 - cam.x * cam.z; const ty = vh / 2 - cam.y * cam.z; world.style.transform = `translate(${tx}px, ${ty}px) scale(${cam.z})`; - world.style.setProperty("--z", cam.z.toFixed(4)); + scaleLabels(); // The stock is one tile-sized layer that only ever translates, so panning never repaints it. const ox = (((tx % TILE) + TILE) % TILE) - TILE; const oy = (((ty % TILE) + TILE) % TILE) - TILE; @@ -172,6 +175,16 @@ function apply() { drawViewport(); } +// Zoomed far out, the pile headings grow so the desk still reads like a map. Set on the few +// headings directly: an inherited custom property on #world restyled the whole desk every frame. +let labelScale = 0; +function scaleLabels() { + const s = Math.min(2.2, Math.max(1, 0.4 / cam.z)); + if (Math.abs(s - labelScale) < 0.005) return; + labelScale = s; + for (const el of labelEls) el.style.scale = String(s); +} + function zoomAt(factor: number, sx: number, sy: number, animate = false) { const from = animate ? goal : cam; const z = clampZ(from.z * factor); diff --git a/src/styles/desk.css b/src/styles/desk.css index e3ce15d..ba6edcb 100644 --- a/src/styles/desk.css +++ b/src/styles/desk.css @@ -684,10 +684,9 @@ html.list .hint-desk { display: none; } - /* zoomed far out, the pile headings grow so the desk still reads like a map */ + /* scaled from the camera (desk.ts) when zoomed far out, growing up from the pile */ html.desk .label { transform-origin: 0 100%; - scale: clamp(1, calc(0.4 / var(--z, 1)), 2.2); z-index: 3; } html.desk .sheet.lifted {