cap the scale at 2x
The quarter steps did not actually shrink it. In a panel around 1500x950 device pixels the fit is 2.56, and floor(2.56 x 4) / 4 is still 2.5 — the finer steps changed where the next size would land, not this one. So a ceiling instead of another nudge: 2x, whatever room the panel has. That is a taste decision rather than a limit of the method — past 2x this stops reading as a window on a desktop — and the panel header has a zoom control, so it is a default, not a verdict. Raise MAX_SCALE and the quarter steps take over again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: de3ed4e6-f88a-429c-94e6-a760336ba83b
This commit is contained in:
@@ -96,6 +96,10 @@ exactly 36 screen pixels, as even as at 2x, and only sub-cell pixels alternate.
|
|||||||
than halves because coarse steps overshoot — with halves this jumped 2x to 2.5x, too small to too large
|
than halves because coarse steps overshoot — with halves this jumped 2x to 2.5x, too small to too large
|
||||||
with nothing in between.
|
with nothing in between.
|
||||||
|
|
||||||
|
The scale is then CAPPED at 2x. Fitting the panel is not the same as looking right, and past 2x this stops
|
||||||
|
reading as a window on a desktop. That is a default, not a verdict — the panel header has a zoom control,
|
||||||
|
and `MAX_SCALE` is one constant.
|
||||||
|
|
||||||
Two things the scale has to know about that are easy to miss. `devicePixelRatio` is not the whole story:
|
Two things the scale has to know about that are easy to miss. `devicePixelRatio` is not the whole story:
|
||||||
the panel header has its own CSS `zoom`, so the effective ratio is `devicePixelRatio × zoom`, read as
|
the panel header has its own CSS `zoom`, so the effective ratio is `devicePixelRatio × zoom`, read as
|
||||||
`getBoundingClientRect().width / offsetWidth`. And the stage is fitted into the box MINUS a margin, because
|
`getBoundingClientRect().width / offsetWidth`. And the stage is fitted into the box MINUS a margin, because
|
||||||
|
|||||||
@@ -27,6 +27,17 @@ const BUTTON_MASK: Record<number, number> = { 0: 1, 1: 2, 2: 4 };
|
|||||||
/** Breathing room around the stage, in device pixels. Small — it is a frame, not a margin. */
|
/** Breathing room around the stage, in device pixels. Small — it is a frame, not a margin. */
|
||||||
const MARGIN_DEVICE_PX = 24;
|
const MARGIN_DEVICE_PX = 24;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ceiling on how large the game is drawn, whatever room the panel has.
|
||||||
|
*
|
||||||
|
* A taste decision, not a limit of the method: fitting the panel is not the same as looking right, and
|
||||||
|
* past 2x this stops reading as a window on a desktop and starts reading as a wall. Raise it and the
|
||||||
|
* quarter steps below take over again.
|
||||||
|
*
|
||||||
|
* The panel header has a zoom control, so this is a default rather than a verdict.
|
||||||
|
*/
|
||||||
|
const MAX_SCALE = 2;
|
||||||
|
|
||||||
// Plugin panels have no localisation mechanism yet — `officerdev`'s `useTranslation`/`panelCatalogs`
|
// Plugin panels have no localisation mechanism yet — `officerdev`'s `useTranslation`/`panelCatalogs`
|
||||||
// (merged by `I18nBridge`) is platform-internal and not exported from the barrel, and
|
// (merged by `I18nBridge`) is platform-internal and not exported from the barrel, and
|
||||||
// `scripts/i18n/scan-hardcoded.ts` explicitly does not scan `plugins/`. So these stay plain English
|
// `scripts/i18n/scan-hardcoded.ts` explicitly does not scan `plugins/`. So these stay plain English
|
||||||
@@ -124,7 +135,8 @@ export const MinesweeperPanel = () => {
|
|||||||
const fit = Math.min(usableW / frame.width, usableH / frame.height);
|
const fit = Math.min(usableW / frame.width, usableH / frame.height);
|
||||||
// Below 1 there is nothing to floor to, so take a unit fraction: the rows that survive are then
|
// Below 1 there is nothing to floor to, so take a unit fraction: the rows that survive are then
|
||||||
// evenly spaced instead of dropped in clumps.
|
// evenly spaced instead of dropped in clumps.
|
||||||
const scale = fit < 1 ? 1 / Math.ceil(1 / fit) : fit < 2 ? 1 : Math.floor(fit * 4) / 4;
|
const snapped = fit < 1 ? 1 / Math.ceil(1 / fit) : fit < 2 ? 1 : Math.floor(fit * 4) / 4;
|
||||||
|
const scale = Math.min(snapped, MAX_SCALE);
|
||||||
return { width: (frame.width * scale) / box.dpr, height: (frame.height * scale) / box.dpr };
|
return { width: (frame.width * scale) / box.dpr, height: (frame.height * scale) / box.dpr };
|
||||||
}, [frame, box]);
|
}, [frame, box]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user