Working with Canvas in Different Screen Sizes

Working with canvas in different screen sizes

So I want to know how to work with a (which will be in fullscreen) on different screen sizes.

This is a common problem that has a pretty easy resolution. Often this is done by separating hard canvas coordinates from what is sometimes called "model" coordinates.

It really depends on how your code is organized, but I assume the game has some height and width to the world that takes up most or all of the screen. The two aspect ratios of the screens you are targeting are 1.5 and 1.666, so you'll want to cater to to the smaller one

So you'll really want to do your game in a set of "model" coordinates that have no bearing on the screen or canvas sizes. Since you are only targeting two screen sizes, your model coordinates can perhaps be 960x640 since that is the smaller of the two aspect ratios. It doesn't have to be. It could be 100x50 for your model coordinates instead. But this example we'll use 960x640 as our model coordinates.

Internally, you never use anything but these model coordinates. You never ever think in any other coordinates when making your game.

When the screen size is 960x640 you won't have to change anything at all since its a 1:1 mapping, which is convenient.

Then when the screen size is actually 800x480, when it comes time to draw to the screen, you'll want to translate all of the model coordinates by (3/4), so the game will be made and internally use 960x480, but it will be drawn in the area of (720x480). You'll also want to take any mouse or touch input and multiply it by (4/3) to turn the screen coordinates into model coordinates.

This translation can be as easy as calling ctx.scale(3/4, 3/4) before you draw everything.

So both platforms will have code that is all written assuming the game is a size of 960x640. The only time that model coordinates become screen coordiantes is when drawing to the canvas (which is a different size) and converting canvas mouse/touch coordinates to model coords.

If that seems confusing to you I can try and make a sample.

Working with canvas in different screen sizes

So I want to know how to work with a (which will be in fullscreen) on different screen sizes.

This is a common problem that has a pretty easy resolution. Often this is done by separating hard canvas coordinates from what is sometimes called "model" coordinates.

It really depends on how your code is organized, but I assume the game has some height and width to the world that takes up most or all of the screen. The two aspect ratios of the screens you are targeting are 1.5 and 1.666, so you'll want to cater to to the smaller one

So you'll really want to do your game in a set of "model" coordinates that have no bearing on the screen or canvas sizes. Since you are only targeting two screen sizes, your model coordinates can perhaps be 960x640 since that is the smaller of the two aspect ratios. It doesn't have to be. It could be 100x50 for your model coordinates instead. But this example we'll use 960x640 as our model coordinates.

Internally, you never use anything but these model coordinates. You never ever think in any other coordinates when making your game.

When the screen size is 960x640 you won't have to change anything at all since its a 1:1 mapping, which is convenient.

Then when the screen size is actually 800x480, when it comes time to draw to the screen, you'll want to translate all of the model coordinates by (3/4), so the game will be made and internally use 960x480, but it will be drawn in the area of (720x480). You'll also want to take any mouse or touch input and multiply it by (4/3) to turn the screen coordinates into model coordinates.

This translation can be as easy as calling ctx.scale(3/4, 3/4) before you draw everything.

So both platforms will have code that is all written assuming the game is a size of 960x640. The only time that model coordinates become screen coordiantes is when drawing to the canvas (which is a different size) and converting canvas mouse/touch coordinates to model coords.

If that seems confusing to you I can try and make a sample.

HTML canvas drawing application breaks on different screen sizes

As Blindman67 points out canvases have 2 sizes. The size that defines the number of pixels that are in the canvas (canvas.width & canvas.height) and the size the canvas is displayed which is set by CSS.

The normal way I resize is like this

function resizeCanvasToMatchDisplaySize(canvas) {

// look up the size the canvas is displayed
var desiredWidth = canvas.clientWidth;
var desiredHeight = canvas.clientHeight;

// if the number of pixels in the canvas doesn't match
// update the canvas's content size.
if (canvas.width != desiredWidth || canvas.height != desiredHeight) {
canvas.width = desiredWidth;
canvas.height = desiredHeight;
}
}

Then I call that before drawing (could be in mouseMove for example). That way it only clears the canvas if the size changed.

You can also use canvas.getBoundingClientRect() and it is technically more correct but it also generates garbage which for my purposes is usually bad. For yours though I suspect it wouldn't matter.

Anytime you set/change the size of a canvas everything about it is reset and it is cleared. That means other settings like fillStyle, lineWidth etc are all reset to defaults when you change the size. If you want something to last past resizing you'll need to record it somehow. Ideas include keeping track of everything drawn so far and drawing it again after resizing. Another idea is to copy the current canvas to another offscreen canvas using something like

 // make a new canvas if we haven't already
offscreenCanvas = offscreenCanvas || document.createElement("canvas");

// make the offscreen canvas match the size of the onscreen canvas
offscreenCanvas.width = onscreenCanvas.width;
offscreenCanvas.height = onscreenCanvas.height;

// get a context for a offscreen canvas
offscreenCanvasContext = offscreenCanvas.getContext("2d");

// clear it just in case it's old and the size didn't change.
offscreenCanvasContext.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);

// copy the onscreen canvas to the offscreen canvas
offscreenCanvasContext.drawImage(onscreenCanvas, 0, 0);

// resize the onscreen canvas
reiszeCanvasToMatchDisplaySize(onscreenCanvas);

// copy back the old content
onscreenCanvasContext.drawImage(offscreenCanvas, 0, 0);

// free the memory used by the offscreen canvas
offscreenCanvas.width = 0;
offscreenCanvas.height = 0;

Of course if the old canvas size was larger you're going to end up clipping content.

Also if your canvas's drawingBuffer size (the number of pixels) doesn't match the display size you can do the math to make the mouse position still match

HTML5 canvas scaling to different detected screen sizes

I'm pretty sure you can only set one width and height in the canvas element itself. If you want to change its size depending on portrait, landscape, etc., you could use CSS media queries. I'm pretty sure that's going to make your canvas not look very high quality in certain situations, since you're essentially just blowing up or shrinking the size of a predefined element.

There might be a fancier way to redraw the canvas depending on screensize, etc., but I haven't tried it.

Real time canvas drawing on different screen sizes

If you also transmit the size of the original canvas then you can work out a scale factor on other devices.

let scale = localCanvas.width / originalCanvas.width;

Then use this scale factor for all drawing.

context.moveTo(coord.x * scale, coord.y * scale);
context.lineTo(nextCoord.x * scale, nextCoord.y * scale);

This assumes the canvas sizes are proportional and the background fits exactly behind the canvas element.

Android: How to handle drawing with canvas methods on different screen sizes?

I missed it the first time going through the Android document; the necessary info is in section "3. Do not use hard-coded pixel values in your code" of the link in my original post.



Related Topics



Leave a reply



Submit