Claude Claude Opus 4.8 commited on
Commit
d90ceb8
·
unverified ·
1 Parent(s): 07fa539

Refit the canvas on any layout change, not just window resize (topbar-wrap bug)

Browse files

On a narrow window the topbar's flex-wrap pushes its actions (the Help "?" among
them) onto a second line, growing the topbar and shrinking the view below it —
but that fires no window `resize` event, so resizeCanvas never ran. The backing
store kept its old, taller size: the never-redrawn strip showed as a thick band
at the bottom of the view, and because the render viewport and the click→world
transform then disagreed on the canvas height, every selection landed offset.

A ResizeObserver on the canvas refits the backing store the instant its box
changes — covering the topbar wrap, the Home button appearing, and the portrait
sheet collapse in one place — and re-clamps the camera into the map. Verified in
a real browser: narrowing to 460px wraps the topbar to 83px and the backing
store tracks the new client box exactly (no stale strip, no offset).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AEQUVetLk31Jj7niDQAsXL

Files changed (1) hide show
  1. main.js +17 -0
main.js CHANGED
@@ -55,6 +55,23 @@ function resizeCanvas() {
55
  }
56
  window.addEventListener("resize", resizeCanvas);
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  // A monitor move (or an OS scaling change) can change devicePixelRatio WITHOUT firing a resize
59
  // event — the CSS layout size is unchanged — leaving the backing store at the old DPR (blurry on
60
  // the sharper screen, oversampled on the other). matchMedia on the current dppx fires once when
 
55
  }
56
  window.addEventListener("resize", resizeCanvas);
57
 
58
+ // The canvas fills a flex region, so its box can change from a LAYOUT shift that fires NO window
59
+ // `resize` event — most visibly the topbar wrapping to a second line on a narrow window (its
60
+ // `flex-wrap` grows it, shrinking the view below), but also the Home button appearing or the
61
+ // portrait sheet collapsing. Without a refit, resizeCanvas never ran: the backing store kept its
62
+ // old, taller size, so the never-redrawn strip showed as a thick band at the bottom AND — because
63
+ // the render viewport and the click→world transform then disagreed on the canvas height — every
64
+ // selection landed offset. A ResizeObserver refits the backing store the instant the box changes,
65
+ // in one place (superseding the ad-hoc triggers above), and re-clamps the camera into the map.
66
+ if (window.ResizeObserver) {
67
+ new ResizeObserver(() => {
68
+ resizeCanvas();
69
+ if (game.state && game.input) {
70
+ clampCamera(game.input.getCamera(), game.state.map, canvas.clientWidth, canvas.clientHeight);
71
+ }
72
+ }).observe(canvas);
73
+ }
74
+
75
  // A monitor move (or an OS scaling change) can change devicePixelRatio WITHOUT firing a resize
76
  // event — the CSS layout size is unchanged — leaving the backing store at the old DPR (blurry on
77
  // the sharper screen, oversampled on the other). matchMedia on the current dppx fires once when