Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Jess
Jess

Posted on • Edited on

     

Resizing HTML5 Canvas and Scaling Sprites

Resizing HTML5 Canvas and Scaling Sprites

I'm working on a game using HTML5/JavaScript and I ran into a problem: Mysprites were created as 8x8px and that would be way too small to view on high resolution displays. Not only that, I wanted the size of the canvas to adapt to whatever display it was being viewed on without distorting my sprites, and I didn't want the canvas to take up the entire window.

8x8 sprite
Example of 8x8px sprite. So tiny!

I wrote a sample to show how to go about scaling the canvas to your browser window up to a max height/width, which you can view oncodepen or clone fromgithub. I'll explain it below:

First, create a<canvas> inside a container<div>.

<divid="game"><canvasid="canvas"></canvas></div>
Enter fullscreen modeExit fullscreen mode

Next, you'll need to add some styling to get the canvas to stay in the center. Remove margin from<body> and<html> and make it take up 100% of the window. Then add flexbox to your container<div> and give it a height and width of 100% as well.

html,body{margin:0;height:100%;width:100%;}#game{display:flex;flex-direction:column;justify-content:center;align-items:center;height:100%;width:100%;}
Enter fullscreen modeExit fullscreen mode

Now get a reference to your<canvas> and canvas context, and set the initial width and height.SIZE refers to the sprite's size, which is 8 pixels wide by 8 pixels tall.map refers to my 2D array. How to create the map is out of the scope of this post, but you can check out the source code to see how it's done.

constctx=document.getElementById('canvas').getContext('2d');// size of each 'tile'constSIZE=8;// native width and height (does not change)constnHeight=SIZE*map.length;constnWidth=SIZE*map[0].length;functionrender(){tiles.forEach(tile=>{ctx.drawImage(tilesheet,tile.srcX,tile.srcY,SIZE,SIZE,tile.x,tile.y,SIZE,SIZE)})}window.addEventListener('load',()=>{ctx.canvas.width=nWidth;ctx.canvas.height=nHeight;buildMap();render();})
Enter fullscreen modeExit fullscreen mode

At this point your canvas is going to be very tiny since it's using your native game resolution (which, in this case is 56x40). Your native game resolution does not change. It's used for your game's logic, such as character movement, collision, etc.

Example of the game map at native resolution of 56x40
Example of the game map at native resolution of 56x40

In order to scale your canvas you'll want to keep track of a separate width and height for your canvas resolution. If you don't want your canvas to extend to the width/height of the window you can add your own max width/height and/or add a percentage of the window that you want to be taken up. You can play around with this; you might not need or want both or either of these settings.

// I just picked 20 at random here.// In this instance maxWidth = 56 * 20 = 1,120 and maxHeight = 40 * 20 = 800constmaxMultiplier=20;constmaxWidth=nWidth*maxMultiplier;constmaxHeight=nHeight*maxMultiplier;// % of browser window to be taken up by the canvas// this can just be set to 1 if you want max height or widthconstwindowPercentage=0.9;// the canvas' displayed width/height// this is what changes when the window is resized// initialized to the native resolutionletcHeight=nHeight;letcWidth=nWidth;
Enter fullscreen modeExit fullscreen mode

Now when you load, you want to set your canvas dimensions to the variables you're using for your canvas resolution as opposed to your native resolution. You also want to set up an event listener to watch forresize, and in there you want to handle your canvas resizing as well as re-render.

window.addEventListener('load',()=>{// initialize native height/widthctx.canvas.width=cWidth;ctx.canvas.height=cHeight;buildMap();resize();render();})window.addEventListener('resize',()=>{resize();render();})functionresize(){cWidth=window.innerWidth;cHeight=window.innerHeight;// ratio of the native game size width to heightconstnativeRatio=nWidth/nHeight;constbrowserWindowRatio=cWidth/cHeight;// browser window is too wideif(browserWindowRatio>nativeRatio){cHeight=Math.floor(cHeight*windowPercentage);// optionalif(cHeight>maxWidth)cHeight=maxHeight;// optionalcWidth=Math.floor(cHeight*nativeRatio);}else{// browser window is too highcWidth=Math.floor(cWidth*windowPercentage);// optionalif(cWidth>maxWidth)cWidth=maxWidth;// optionalcHeight=Math.floor(cWidth/nativeRatio);}// set the canvas style width and height to the new width and heightctx.canvas.style.width=`${cWidth}px`;ctx.canvas.style.height=`${cHeight}px`;}
Enter fullscreen modeExit fullscreen mode

Inresize(), you first setcWidth andcHeight (the canvas resolution variables) to the window'sinnerWidth andinnerHeight. Then you need to get the ratio of width to height for both your native resolution and your browser window. If the ratio of the window'sinnerWidth /innerHeight (cWidth/cHeight) is greater than the native resolution ratio (nWidth/nHeight) then the browser is too wide and you need to recalculate the width so it meets the correct ratio. Otherwise, the browser window is too high and you need to recalculate the height.

If you want to set a max window percentage you can set the new canvas width/height by first multiplying their values bymaxPercentage. If you want to use a maxWidth/maxHeight you can check if thecWidth andcHeight values are greater, and if so, set them to their max. After, or instead of, all of that, you can set the final new width or height values (depending on which condition you hit). The newcWidth is calculated bymultiplyingcHeight bynativeRatio and the newcHeight is calculated bydividingcWidth bynativeRatio.

Next, set the canvas'style property's width and height to the newcWidth andcHeight. "Canvas.width and canvas.height set the size of the canvas. canvas.style.width and canvas.style.height set the resolution."

Finally, addimage-rendering: pixelated to yourcanvas styles so that your pixel art isn't blurry.

canvas{image-rendering:pixelated;}
Enter fullscreen modeExit fullscreen mode
Example of the game map at native resolution of 56x40
Example of the game map upscaled to approx. 864x617

That should be it. I know I assumed a lot of prior knowledge with canvas and setting up sprites and the game map, so if you're struggling leave a comment and maybe I, or another reader, can help!


Here are some links if you're interested in reading or watching more about this topic.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Software Engineer / Flatiron School grad
  • Location
    NJ
  • Education
    Flatiron School
  • Pronouns
    she / her
  • Work
    Software engineer
  • Joined

More fromJess

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp