简体   繁体   中英

Canvas - Keeping aspect ratio while also keeping pixel amount

I have a canvas like so: 画布上有一只香蕉鸭和一些奶酪But when resizing the window and redrawing, you can get anything in between. 只有几块奶酪的鸭子

I keep the aspect ratio with this code:

function setCanvasSize(){
    ctx.canvas.width = (window.innerWidth)*0.8;
    ctx.canvas.height= (window.innerWidth)*0.5;
}
setCanvasSize()
$(window).resize(function(){
    setCanvasSize()
})

and that keeps it nice and clean, the same-looking size, but how many pixels are in there changes, so when my program draws, it's always in a different spot, although the aspect is the same, so it looks really weird.

Any way that I can somehow tweak how I draw things, or a way to keep how many pixels there are?

Edit: code snippet to reproduce

 const ctx = document.getElementById('game').getContext("2d"); $('#game').css('width', '100%'); $(window).resize(function(){ $('#game').height($('#game').width() / 2.031); }); const imageAt=((href,x,y,sizex,sizey)=>{ var img = new Image(); img.addEventListener('load', function() { ctx.drawImage(img, x, y, sizex, sizey); }, false); img.src = href }) imageAt('https://b.thumbs.redditmedia.com/bZedgr0gq7RQBBnVYVc-Nmzdr-5vEUg4Dj8nTrMb7yA.png',0,0,50,50)
 #game{ padding-left: 0; padding-right: 0; display: block; margin: 0; border:5px solid green; padding:0; } #vertical-center { display: flex; align-items: center; justify-content: center; height: 100%; background: black; padding:0; } body{ background-color: black; padding:0; }
 <html> <head> <title>Tiled Canvas Engine Test 1</title> <meta name="viewport" content="width=device-width, initial-scale=0.75"> <link rel="stylesheet" href="./index.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="engine.js"></script> <script defer src="script.js"></script> </head> <body> <div id="vertical-center"> <canvas id="game"></canvas> </div> </body> </html>

In order to render properly the canvas element needs to have its width and height attributes set explicitly. This will define the viewport into which graphics will be draw. The style attributes for width and height which is what jQuery sets via the width() and height() functions will only stretch the viewport to fit. (Note: for high DPI displays, ie Retina, you will want to double the dimensions when specifying the attributes).

The critical change is this:

  // Updates the actual width and height attributes
  canvas.width = $('#game').width() * window.devicePixelRatio;
  canvas.height = $('#game').height() * window.devicePixelRatio;

The snippet below also handles clearing the canvas, redrawing the image, and saving the Image once loaded:

 const ctx = document.getElementById('game').getContext("2d"); $('#game').css('width', '100%'); $(document).ready(handleResize); $(window).resize(handleResize); function handleResize() { // sets the style.height and style.width for the canvas $('#game').height($('#game').width() / 2.031); let canvas = $('#game').get(0); // Updates the actual width and height attributes canvas.width = $('#game').width() * window.devicePixelRatio; canvas.height = $('#game').height() * window.devicePixelRatio; // redraw if (img) { redraw(); } } var img; const imageAt = ((href, x, y, sizex, sizey) => { img = new Image(); img.addEventListener('load', function() { ctx.drawImage(img, x, y, sizex, sizey); }, false); img.src = href }) imageAt('https://b.thumbs.redditmedia.com/bZedgr0gq7RQBBnVYVc-Nmzdr-5vEUg4Dj8nTrMb7yA.png', 0, 0, 50 * window.devicePixelRatio, 50 * window.devicePixelRatio) function redraw() { ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); ctx.drawImage(img, 0, 0, 50 * window.devicePixelRatio, 50 * window.devicePixelRatio); }
 #game { padding-left: 0; padding-right: 0; display: block; margin: 0; border: 5px solid green; padding: 0; } #vertical-center { display: flex; align-items: center; justify-content: center; height: 100%; background: black; padding: 0; } body { background-color: black; padding: 0; }
 <html> <head> <title>Tiled Canvas Engine Test 1</title> <meta name="viewport" content="width=device-width, initial-scale=0.75"> <link rel="stylesheet" href="./index.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script src="engine.js"></script> <script defer src="script.js"></script> </head> <body> <div id="vertical-center"> <canvas id="game"></canvas> </div> </body> </html>

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