简体   繁体   中英

Scale canvas width and height to be as large as possible but maintain aspect ratio (JS)

If I have a canvas element that is a certain width and height, eg

<canvas id="display" width="900" height="650" tabindex=0></canvas>

and I want to scale up the width and height of the canvas to as large as possible while being contained within the viewport without changing the aspect ratio or increasing the overall area for objects to be displayed within the canvas.

This means that if a window is width 2200 and height 1300 , both the display width and height of the canvas will be doubled (and no larger because otherwise the height could not be contained) and the canvas will have the new dimensions 1800 and 1300 .

However, I am scaling up the CSS display height of the canvas element, not the canvas itself, which means that objects inside the canvas should also have their dimensions increased.

canvas {
  width: ...
  height: ...
}

It would be even better if the canvas can rescale itself when the window is resized, perhaps with an event listener.

Is there any way to do this in JS?

Scale to fit

You have to define the aspect. This can be done by just defining a default size.

const defWidth = 1920;
const defHeight = 1080;

Then you can listen to the window resize event and resize the canvas to fit.

function resizeEventHandler(){
    // get the max size that fits both width and height by finding the min scale
    var canvasScale = Math.min(innerWidth / defWidth, innerHeight / defHeight);
    // or for max size that fills
    // canvasScale = Math.max(innerWidth / defWidth, innerHeight / defHeight);

    // now set canvas size and resolution to the new scale
    canvas.style.width = (canvas.width = Math.floor(defWidth * canvasScale)) + "px";
    canvas.style.height = (canvas.height = Math.floor(defHeight * canvasScale)) + "px";
}

Because the canvas resolution must be an integer the aspect may be out by a pixel. But there is nothing that can be done about that.

Ended up finding my own solution, if there is a more elegant one available then please inform me.

// get maximum possible size for canvas while maintining aspect ratio
function resizeEventHandler(){
  var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  if(w/canvas.width > h/canvas.height){
    canvas.style.width = "calc("+canvas.width+" / "+canvas.height+" * 100vh)";
    canvas.style.height = "calc(100vh)";
  } else {
    canvas.style.width = "calc(100vw)";
    canvas.style.height = "calc("+canvas.height+" / "+canvas.width+" * 100vw)";
  }
}
resizeEventHandler();
window.addEventListener("resize", resizeEventHandler);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM