Commit 13cbc287 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: the chess board overflowed any padded container

ChessBoard sized itself from container.clientWidth, which INCLUDES padding, so
inside a padded container the board came out exactly the padding too wide. On the
puzzle screen that pushed the whole page 4px sideways and hung the board off the
edge. Sizing now measures the container's content box.

resize() had a second bug: it set canvas.width/height (the backing store) but
never the CSS width/height, so after any resize the element laid out at its
attribute width — devicePixelRatio times too large. It also now resets the
transform before scaling rather than relying on the implicit reset.

Both paths share one availableSize(), so they can no longer disagree.

Local audit is clean across all scenes at 360/390/430px.
Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
parent 9030409a
...@@ -265,10 +265,24 @@ export class ChessBoard { ...@@ -265,10 +265,24 @@ export class ChessBoard {
this.bindEvents(); this.bindEvents();
} }
/**
* The largest square that fits inside the container's CONTENT box.
*
* clientWidth includes padding, so sizing from it overflowed any padded
* container by exactly the padding — which is why the puzzle board hung off
* the edge of the screen and pushed the page sideways.
*/
availableSize() {
const cs = getComputedStyle(this.container);
const padX = (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0);
const padY = (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);
const w = (this.container.clientWidth || this.wrapper.clientWidth || 360) - padX;
const h = (this.container.clientHeight || 500) - padY;
return Math.max(120, Math.min(Math.floor(w), Math.floor(h), 500));
}
setupCanvas() { setupCanvas() {
const containerH = this.container.clientHeight || 500; const size = this.availableSize();
const containerW = this.container.clientWidth || this.wrapper.clientWidth || 360;
const size = Math.min(containerW - 4, containerH - 4, 500);
this.squareSize = size / 8; this.squareSize = size / 8;
this.wrapper.style.maxWidth = size + 'px'; this.wrapper.style.maxWidth = size + 'px';
const { canvas, ctx } = createCanvas(this.wrapper, size, size); const { canvas, ctx } = createCanvas(this.wrapper, size, size);
...@@ -506,12 +520,21 @@ export class ChessBoard { ...@@ -506,12 +520,21 @@ export class ChessBoard {
} }
resize() { resize() {
const size = Math.min(this.wrapper.clientWidth || 360, 400); // Both the backing-store size and the CSS size. Setting only canvas.width
// lays the element out at its attribute width — devicePixelRatio times too
// large — which overflowed the board on every 2x phone.
const size = this.availableSize();
this.squareSize = size / 8; this.squareSize = size / 8;
this.size = size; this.size = size;
this.wrapper.style.maxWidth = size + 'px';
const dpr = window.devicePixelRatio || 1; const dpr = window.devicePixelRatio || 1;
this.canvas.width = size * dpr; this.canvas.width = size * dpr;
this.canvas.height = size * dpr; this.canvas.height = size * dpr;
this.canvas.style.width = size + 'px';
this.canvas.style.height = size + 'px';
// Setting canvas.width resets the transform, so this is not cumulative.
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
this.ctx.scale(dpr, dpr); this.ctx.scale(dpr, dpr);
this.draw(); this.draw();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment