Canvas device orientation scaling

Viewed 701

I made a racetrack game. I am trying to make it scalable on mobile devices.

I was able to make it look fine when device orientation is normal (vertical):

![enter image description here

But when I rotate the device to horizontal view, this happens: (how to zoom it out a bit )?

enter image description here

What would you recommend doing? I used display: none to hide the images. I would really appreciate any help.

Edit: I've managed to do this but the view is still too much zoomed, any ideas?

const width = 800;
const height = 600;
const pixelRatio = window.devicePixelRatio || 1;
canvas.width = width * pixelRatio;
canvas.height = height * pixelRatio;

canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;

// for sprites scaled up to retina resolution
canvas.mozImageSmoothingEnabled = false;
canvas.imageSmoothingEnabled = false;

c.scale(pixelRatio, pixelRatio);
<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, height=device-height">

    <!-- <meta name="viewport" content="width=device-width, initial-scale=1"> -->
    <title>Canvas Story</title>
    <style type="text/css">
        * {
            margin: 0;
            padding: 0;
        }
        canvas {

            display: block;
        }
        body {
            margin: 0;
        } 
        #container {
            margin: 0 auto;
            width: 800px;
            height: 600px;
            overflow: hidden;
            position: relative;
            border: 1px solid #000;
            border-radius: 10px;
            margin-top: 2px;
        } 
    </style>
</head>

<body>
    <br/>
    
    <img id="obstacle" src="obstacle.png" style="display: none;" />
        <img id="bonus" src="bonus.png" style="display: none;" />
        <img id="bullet" src="bullet.png" style="display: none;" />
        <img id="car" src="car.png" style="display: none;" />

    <div id="container">
        <canvas id="ltpcanvas"></canvas>
    </div>

    <div class="circleBase" id="rotateMode" style="margin:0 auto;">
        <button id="left" onmousedown="leftKeyPressed()" onmouseup="leftKeyReleased()" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-arrow-left"></span></button>
        <button id="right" onmousedown="rightKeyPressed()" onmouseup="rightKeyReleased()" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-arrow-right"></span></button>
        <button id="middle" onclick="bulletsPush()" class="btn btn-default btn-sm"><span class="glyphicon glyphicon glyphicon-record"></span></button>
        <button id="up" onmousedown="upKeyPressed()" onmouseup="upKeyReleased()" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-arrow-up"></span></button>
        <button id="down" onmousedown="downKeyPressed()" onmouseup="downKeyReleased()" class="btn btn-default btn-sm"><span class="glyphicon glyphicon-arrow-down"></span></button>
    </div>
    
    
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <link rel="stylesheet" href="css.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="canvas.js"></script>

    

</body>

</html>
4 Answers

use this in head tag:

<meta name="viewport" content="width=device-width, initial-scale=1">

The width=device-width part sets the width of the page to follow the screen-width of the device (which will vary depending on the device).

The initial-scale=1.0 part sets the initial zoom level when the page is first loaded by the browser.

and in animate add these:

            c.clearRect(0, 0, canvas.width, canvas.height);
            drawCanvas(boundaryLeftOffset - 2, 0,window.innerWidth, 
            window.innerHeight, 'grey');

Update canvas size or anything you need, in a callback for resize events of the window object:

window.addEventListener('resize', function() {
    // canvas resize, etc.
}, false);

if <meta name="viewport" content="width=device-width, initial-scale=1"> doesnt work then you might want to look into the @media query. Its helped me a lot in the past and I think it will help you especially if you know the resolution of the monitors/screens.

I think you need to set the size of the canvas based on the size of the viewport (and be sure to do this if the viewport size changes (E.g. by rotating screen):

// Set canvas size (how many 'pixels' are on the canvas)
// NOTE CSS determines how large the canvas is, this determines
// the size of the things you draw on it.
const width = 800;
const height = 600;
const canvasAspectRatio = width / height;

// Also define the gap we want at the edges:
const edgeMargin = 10;

// Set the number of 'pixels' in the canvas.
canvas.width = width;
canvas.height = height;

// Sets the canvas size based on the window height and width
function setCanvasElementSize () {
  const windowWidth = window.innerWidth;
  const windowHeight = window.innerHeight;

  // Work out the orientation of the device.
  const isPortrait = window.innerHeight > window.innerWidth;

  if (isPortrait) {
    // We want to constrain the canvas by its width
    canvas.style.width = windowWidth - (2 * edgeMargin);
    // The height depends on the width to ensure we don't stretch pixels
    // on the canvas.
    canvas.style.height = canvas.style.width / canvasAspectRatio;
  } else {
    // constrain by height
    canvas.style.height = windowHeight - (2 * edgeMargin);
    canvas.style.width = canvas.style.height * canvasAspectRatio;
  }
}

// Call the function once initially to size the canvas
setCanvasElementSize();

// Also add a resize listener so we can ensure the canvas is 
// adjusted when the screen rotates.

// BONUS: Only do this once per animation frame.
let rafRequest = null;
window.addEventListener('resize', function () {
  if (rafRequest) {
    clearAnimationFrame(animationFrameReference);
  }

  let rafRequest = requestAnimationFrame(function () {
    rafRequest = null;
    setCanvasElementSize();
  });
});

CAVEATS:

  1. I haven't tested this code, there may be typos!
  2. Some mobile browsers behave differently to others when it comes to measuring the window size. For example, some do not take into account the size of the address bar, or whether or not the keyboard is visible. This is kind of beyond the scope of the question though. If you want to adjust for this you'll have to do some more extensive testing/research then increment or decrement the size of the canvas in setCanvasElementSize() accordingly.
Related