Jump to content

Scaling logic behaves in a way I cannot understand or debug


danielkill
 Share

Recommended Posts

Hi, my goal is to have a canvas that spans 80% of the users browser and keeps aspect ratio of 16:9. I was trying different approaches throughout today, failing to reach the goal, but here's the idea I came up with that works on paper and in my head, but not in practice. Can anyone see where's the problem in my line of thinking?

Conceptually: I pretend I have 1280x720 available and use it to position whatever I want on the canvas, using the 1280x720 coordinates system.

Then I find out what screen size I have available and compute following values using following formulas:

  1. newWidth = window.innerWidth * 0.8
  2. newHeight = newWidth * (16/9)
  3. scaleFactor = newWidth / lastWidth (when this is first called, lastWidth is 1280)

In the test environment, I have larger screen than this, so I start with scaleFactor=1.2 and I have two sprite circles, for which I update both coords by sprite.x = sprite.x*scaleFactor equation. For moving the sprites at corresponding scale, this seem to work correctly.

Similarly, I thought that doing sprite.set.scale(scaleFactor) or sprite.set.scale(scaleFactor, scaleFactor), will do the job correctly and performed following test:

1. Have it loaded for the first time in big window, with values being properly scaled (success?)
2. Have it loaded in a smaller window by clicking "Restore down" on window control, which scales things down by three times, scale factor 0.3, everything seems legit.
3. Have it loaded back in the big window as in (1), scale factor = 3 (scaling 300% up, as it scaled to 30% before), which works for coordinates, but scale is off (its way bigger, I will attach screens to demonstrate this).

Why is 3 happening?

// Hopefully minimum viable example of what is going on in my code, with unnecessary/irrelevant parts removed

const targetAspectRatio = 16 / 9;
const canvasWidthPercentage = 80;

const baseWidth = 1280;
const baseHeight = 720;
let scaleFactor = 1.;

const initialWidth = window.innerWidth * (canvasWidthPercentage / 100); 
const initialHeight = initialWidth / targetAspectRatio;

// Keeping track of previous dimensions
let lastWidth = baseWidth;
let lastHeight = baseHeight;

const app = new PIXI.Application({
  width: baseWidth,
  height: baseHeight,
  resolution: window.devicePixelRatio || 1,
});
document.body.appendChild(app.view);

/* Here I spawn circles -> redacted from this sample, but attached below */

function resizeHandler() {
  const newWidth = window.innerWidth * (canvasWidthPercentage / 100);
  const newHeight = newWidth / targetAspectRatio;
  scaleFactor = newWidth / lastWidth; // scaleWidth == scaleHeight, due to aspect ratio lock I believe

  console.table({/* Debug you see in attachments */})
            

  // Update the renderer size
  app.renderer.resize(newWidth, newHeight);

  displayedSprites.forEach((sprite) => {
    sprite.scale.set(scaleFactor)
    sprite.x = sprite.x * scaleFactor;
    sprite.y = sprite.y * scaleFactor; 
    console.log("On window resize moved sprite to [x,y]=["+sprite.x+","+sprite.y+"]")
  });
  lastWidth = newWidth;
  lastHeight = newHeight;            
}


window.addEventListener('resize', resizeHandler);
resizeHandler();

 

Wasn't sure it is relevant, but here's how I spawn those circles:

const spawnCircle = (x, y) => {
	let graphics = new PIXI.Graphics();

	graphics.beginFill(0xFF0000);
	graphics.drawCircle(50, 50, 50); // center coords (x,y) and radius
	graphics.endFill();

	const texture = app.renderer.generateTexture(graphics);

	const sprite = new PIXI.Sprite(texture);

	sprite.x = x * scaleFactor;
	sprite.y = y * scaleFactor;
	console.log("Spawning a circle at [x,y]=["+sprite.x+","+sprite.y+"]")

	app.stage.addChild(sprite);
	displayedSprites.push(sprite);
}
spawnCircle(150, 100);
spawnCircle(150, 300);

 

1stload_big-window.jpg

1stload_big-window_debug.jpg

2ndload_small_window.jpg

2ndload_small_window_debug.jpg

3rd_restore_to_big.jpg

3rd_restore_to_big_debug.jpg

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...