Skip to content

Commit 1746102

Browse files
committed
Bug fix unstyled canvas resizing
1 parent 0e37140 commit 1746102

File tree

2 files changed

+77
-51
lines changed

2 files changed

+77
-51
lines changed

.changeset/forty-lamps-brake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"stage-js": patch
3+
---
4+
5+
Fix unstyled canvas resizing loop

src/core/root.ts

Lines changed: 72 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ export class Root extends Component {
5959
dom: HTMLCanvasElement | null = null;
6060
context: CanvasRenderingContext2D | null = null;
6161

62-
/** @internal */ pixelWidth = -1;
63-
/** @internal */ pixelHeight = -1;
62+
/** @internal */ clientWidth = -1;
63+
/** @internal */ clientHeight = -1;
6464
/** @internal */ pixelRatio = 1;
65-
/** @internal */ drawingWidth = 0;
66-
/** @internal */ drawingHeight = 0;
65+
/** @internal */ canvasWidth = 0;
66+
/** @internal */ canvasHeight = 0;
6767

6868
mounted = false;
6969
paused = false;
@@ -168,6 +168,62 @@ export class Root extends Component {
168168
/** @internal */ _lastFrameTime = 0;
169169
/** @internal */ _mo_touch: number | null = null; // monitor touch
170170

171+
resizeCanvas() {
172+
const newClientWidth = this.canvas.clientWidth;
173+
const newClientHeight = this.canvas.clientHeight;
174+
175+
// canvas display size is not changed
176+
if (this.clientWidth === newClientWidth && this.clientHeight === newClientHeight) return;
177+
178+
this.clientWidth = newClientWidth;
179+
this.clientHeight = newClientHeight;
180+
181+
const notStyled =
182+
this.canvas.clientWidth === this.canvas.width &&
183+
this.canvas.clientHeight === this.canvas.height;
184+
185+
let pixelRatio: number;
186+
187+
if (notStyled) {
188+
// If element is not styled, changing canvas rendering size will change its display size,
189+
// which creates a loop of resizing. So we ignore pixel ratio and keep current rendering size.
190+
pixelRatio = 1;
191+
this.canvasWidth = this.canvas.width;
192+
this.canvasHeight = this.canvas.height;
193+
} else {
194+
pixelRatio = this.pixelRatio;
195+
this.canvasWidth = this.clientWidth * pixelRatio;
196+
this.canvasHeight = this.clientHeight * pixelRatio;
197+
198+
if (this.canvas.width !== this.canvasWidth || this.canvas.height !== this.canvasHeight) {
199+
// canvas rendering size is changed
200+
this.canvas.width = this.canvasWidth;
201+
this.canvas.height = this.canvasHeight;
202+
}
203+
}
204+
205+
console.debug &&
206+
console.debug(
207+
"Resize: [" +
208+
this.canvasWidth +
209+
", " +
210+
this.canvasHeight +
211+
"] = " +
212+
pixelRatio +
213+
" x [" +
214+
this.clientWidth +
215+
", " +
216+
this.clientHeight +
217+
"]",
218+
);
219+
220+
this.viewport({
221+
width: this.canvasWidth,
222+
height: this.canvasHeight,
223+
ratio: pixelRatio,
224+
});
225+
}
226+
171227
/** @internal */
172228
onFrame = (now: number) => {
173229
this.frameRequested = false;
@@ -177,45 +233,7 @@ export class Root extends Component {
177233
}
178234

179235
this.requestFrame();
180-
181-
const newPixelWidth = this.canvas.clientWidth;
182-
const newPixelHeight = this.canvas.clientHeight;
183-
184-
if (this.pixelWidth !== newPixelWidth || this.pixelHeight !== newPixelHeight) {
185-
// viewport pixel size is not the same as last time
186-
this.pixelWidth = newPixelWidth;
187-
this.pixelHeight = newPixelHeight;
188-
189-
this.drawingWidth = newPixelWidth * this.pixelRatio;
190-
this.drawingHeight = newPixelHeight * this.pixelRatio;
191-
192-
if (this.canvas.width !== this.drawingWidth || this.canvas.height !== this.drawingHeight) {
193-
// canvas size doesn't math
194-
this.canvas.width = this.drawingWidth;
195-
this.canvas.height = this.drawingHeight;
196-
197-
console.debug &&
198-
console.debug(
199-
"Resize: [" +
200-
this.drawingWidth +
201-
", " +
202-
this.drawingHeight +
203-
"] = " +
204-
this.pixelRatio +
205-
" x [" +
206-
this.pixelWidth +
207-
", " +
208-
this.pixelHeight +
209-
"]",
210-
);
211-
212-
this.viewport({
213-
width: this.drawingWidth,
214-
height: this.drawingHeight,
215-
ratio: this.pixelRatio,
216-
});
217-
}
218-
}
236+
this.resizeCanvas();
219237

220238
const last = this._lastFrameTime || now;
221239
const elapsed = now - last;
@@ -234,9 +252,9 @@ export class Root extends Component {
234252
this._mo_touch = this._ts_touch;
235253
this.sleep = false;
236254

237-
if (this.drawingWidth > 0 && this.drawingHeight > 0) {
255+
if (this.canvasWidth > 0 && this.canvasHeight > 0) {
238256
this.context.setTransform(1, 0, 0, 1, 0, 0);
239-
this.context.clearRect(0, 0, this.drawingWidth, this.drawingHeight);
257+
this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
240258
if (this.debugDrawAxis > 0) {
241259
this.renderDebug(this.context);
242260
}
@@ -434,14 +452,17 @@ export class Root extends Component {
434452
const cameraX = camera?.e || 0;
435453
const cameraY = camera?.f || 0;
436454

437-
const scaleX = this.pin("scaleX");
438-
const scaleY = this.pin("scaleY");
455+
const pinScaleX = this.pin("scaleX");
456+
const pinScaleY = this.pin("scaleY");
457+
458+
const scaleX = pinScaleX * cameraZoomX;
459+
const scaleY = pinScaleY * cameraZoomY;
439460

440-
this.pin("scaleX", scaleX * cameraZoomX);
441-
this.pin("scaleY", scaleY * cameraZoomY);
461+
this.pin("scaleX", scaleX);
462+
this.pin("scaleY", scaleY);
442463

443-
this.pin("offsetX", cameraX - viewboxX * scaleX * cameraZoomX);
444-
this.pin("offsetY", cameraY - viewboxY * scaleY * cameraZoomY);
464+
this.pin("offsetX", cameraX - viewboxX * scaleX);
465+
this.pin("offsetY", cameraY - viewboxY * scaleY);
445466
} else if (viewport) {
446467
this.pin({
447468
width: viewport.width,

0 commit comments

Comments
 (0)