Yotam
Yotam

Reputation: 10685

Canvas width in CSS looks bad and doesn't agree with javascript code

I'm working on a small webpage that generates a figure based on user input. I plan to place a canvas in the html code, and to use javascript to create the image. The problem I have is that the canvas size as defined in the css file seems to only scale a small canvas and not to actually create a bigger one. This is my html code

function test() {
    var canvas = document.getElementById("canvas");
    if (null == canvas || !canvas.getContext) return;

    ctx = canvas.getContext("2d");

    for (var i = 0; i <= canvas.width; i += 50) {
        for (var j = 0; j < canvas.height; j += 20) {
            ctx.fillText(j, i, j);
        }
    }
}
body {
    background-color: rgba(0, 100, 100, 0.2);
    width: 100%;
}
    
canvas {
    width: 100%;
}
<html>

<head>
   <meta charset="utf-8">
   <title>
      Test
   </title>

   <meta name="viewport" content="width=device-width, initial-scale=1.0,
        maximum-scale=1.0, user-scalable=no" />

   <link rel="stylesheet" href="css/styles.css">

   <script language="javascript" type="text/javascript" src="js/worker.js">
   </script>

</head>

<body onload="test()">
    <canvas id="canvas"></canvas>
</body>

</html>

The output, looks like this (The same happens when I replace the width of the canvas in the cssfile to 100%)

enter image description here

why wouldn't I get smaller numbers that go up to 700?

Upvotes: 2

Views: 430

Answers (2)

User K
User K

Reputation: 380

Use Javascript to set the canvas width and height using window.innerWidth & window.innerHeight.
This will match the viewport of the device.

function test() {
   var canvas = document.getElementById("canvas");
   canvas.width = window.innerWidth;
   canvas.height = window.innerHeight;
   if (null == canvas || !canvas.getContext) return;

   ctx = canvas.getContext("2d");

   for (var i = 0; i <= canvas.width; i += 50) {
      for (var j = 0; j < canvas.height; j += 20) {
         ctx.fillText(j, i, j);
      }
   }
}

Upvotes: 0

Joseph Marikle
Joseph Marikle

Reputation: 78520

Your mystery width and height are coming from the canvas default values in the absence of width and height attributes. These default values are 300 for width and 150 for height. Read more on the HTMLCanvasElemnet here.

To correct this behaviour, you can either give it a static width and height using those attributes (not ideal), or you can set the width and height with javascript. I suggest using offsetWidth and offsetHeight properties. It will also be necessary to set these values whenever the window resizes. That can be done with an event listener. Here's a demo:

https://jsfiddle.net/f7btghdr/2/

var canvas = document.getElementById("canvas");

ctx=canvas.getContext("2d");

function test() {
  for (var i=0; i <= canvas.offsetWidth; i += 50){
    for (var j=0; j <= canvas.offsetHeight; j += 20){
      ctx.fillText(i + 'x' + j,i,j);
    }
  }
}

function adjustCanvas() {
  canvas.width = canvas.offsetWidth;
  canvas.height = canvas.offsetHeight;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.textBaseline="top";
  test();
}

window.addEventListener('resize', adjustCanvas);
adjustCanvas();
html, body, canvas {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  display: block;
}
<canvas id="canvas"></canvas>

Edit

Per Kaiido's comments below, the following snippet is probably a better approach to this. Of note, the clearRect call was superfluous, getBoundingClientRect should give more precise values for the width and height of the canvas, and the canvas CSS is also unnecessary (it gets overridden with the width and height properties right away anyway). Below is a revised demo with these changes in place.

var canvas = document.getElementById("canvas");

ctx=canvas.getContext("2d");

function test() {
  for (var i=0; i <= canvas.offsetWidth; i += 50){
    for (var j=0; j <= canvas.offsetHeight; j += 20){
      ctx.fillText(i + 'x' + j,i,j);
    }
  }
}

function adjustCanvas() {
  var dimensions = canvas.parentNode.getBoundingClientRect();
  canvas.width = dimensions.width;
  canvas.height = dimensions.height;
  ctx.textBaseline="top";
  test();
}

window.addEventListener('resize', adjustCanvas);
adjustCanvas();
html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  display: block;
}

.canvas-wrapper {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

canvas {
  display: block;
}
<div class="canvas-wrapper">
  <canvas id="canvas"></canvas>
</div>

Upvotes: 3

Related Questions