Re-fit the viewport whenever the canvas box moves

The portrait fit was right, it just ran once and too early: iOS Safari lays the
page out before its toolbars settle, so the box the first fit measured was short
by a strip — and no window resize follows, because the page never scrolls. The
height only came good after a rotate and back, which IS a resize. A
ResizeObserver on the canvas watches the box itself, so every cause is covered
(bars settling, rotation, split view, zoom) without guessing which event or delay
to listen for. It only rewrites the backing store, never the CSS box, so it
cannot feed itself.

Verified both directions: box grows -> logical H 585 -> 671, box back -> 585,
logical aspect matching the box aspect each time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
wuwiandClaude Opus 5 committed 2026-07-31 08:49:02 +02:00
1 parent 5f97c7cff4
commit e8116c6abb
2 files changed
+10 -2

No files matched your search

+1 -1
View File
@@ -89,6 +89,6 @@
<p id="build"></p>
</div>
</div>
<script type="module" src="main.js?v=51"></script>
<script type="module" src="main.js?v=52"></script>
</body>
</html>
+9 -1
View File
@@ -119,7 +119,15 @@ export function fitViewport() { // landscape 480x270; portrait 270 wide and as T
// inset in logical px so the rack can lift clear of the home indicator.
measureSafe((cv.clientWidth || innerWidth) / w);
}
addEventListener('resize', fitViewport);
// The fit was correct but it ran exactly once, too early. iOS Safari lays the page out BEFORE its
// toolbars settle, so the box the first fit measured was ~150 CSS px short — and no window `resize`
// follows, because the page never scrolls. The height only came right after a rotate and back, which
// IS a resize. Watching the canvas box itself covers every cause (bars settling, rotation, split
// view, zoom) instead of guessing which event or delay to listen for — and the observer's initial
// callback is the real initialisation. fitViewport is idempotent, and it only changes the backing
// store, never the CSS box, so this cannot feed itself.
addEventListener('resize', fitViewport); // fallback for browsers without the observer
new ResizeObserver(fitViewport).observe(cv); // the box itself is the signal, whatever moved it
// The aim camera: while the slingshot is drawn the view rises and leans back a little, which
// steepens the look down the court. That extra depth is what makes a shambler standing right