1

I was trying to draw a circle in the canvas when I noticed something strange - basically when I defined the canvas' dimensions by CSS, the element went out of scale - like it looked "squished".

But if I set the dimensions though the "width" and "height" HTML attributes, it rendered normally.

$(document).ready(function() {

  function highlightAreaTrial(elementId, x, y, radius) {
    console.log("x, y: " + x + ", " + y);
    canvas = document.getElementById(elementId);
    ctx = canvas.getContext('2d');
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, 2*Math.PI);
    ctx.strokeStyle="#FF0000";
    ctx.stroke();
  }

  highlightAreaTrial("trial", 50, 50, 20);
  highlightAreaTrial("myCanvas", 50, 50, 20);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="trial" style="height: 100px; width: 100px; border: 1px solid black;"></canvas>
    
<canvas id="myCanvas" width="100" height="100" style="border:1px solid #d3d3d3;"></canvas>

Here's a fiddle: https://jsfiddle.net/codeapprenti/vnoukemm/

Can someone explain this behaviour?

Thanks.

APAD1
  • 13,509
  • 8
  • 43
  • 72
Code Apprentice
  • 522
  • 2
  • 7
  • 19
  • 1
    I've updated your question so that both examples are using the same dimensions in order to reproduce the issue you are describing. – APAD1 Jan 12 '16 at 19:52
  • 1
    CSS is for pixels. You set the number of pixels across and down in the CSS. The Element attributes are the screen display dimensions and define the size on the Page/Window. Though this is only the case when you have the canvas in the Markup. If you create a canvas in Javascript the element width and height attributes also set the canvas pixel resolution. – Blindman67 Jan 12 '16 at 20:23
  • 1
    Your question is often asked here on SO. When resizing the canvas using CSS you are stretching (or squishing) pixels until the original drawing fits inside the new CSS dimensions. Think of that as a T-shirt with logo. If you stretch the shirt the logo will deform by stretching ... same with canvas drawings -- they stretch and shrink. On the other hand changing the canvas element width/height (`canvas.width=400`) you are actually *adding or removing pixels* to the canvas drawing surface -- so no deforming takes place. If that makes sense you might delete your question b/ it is a duplicate. ;-) – markE Jan 12 '16 at 20:27
  • 1
    @markE Really clear explanation, but just to respect everyone who's put in the effort of commenting and answering, I think I'll keep it. But thanks. :) – Code Apprentice Jan 12 '16 at 21:07

2 Answers2

3

According to the relevant spec:

4.8.11 The canvas element — HTML5

The canvas element has two attributes to control the size of the coordinate space: width and height. These attributes, when specified, must have values that are valid non-negative integers. The rules for parsing non-negative integers must be used to obtain their numeric values. If an attribute is missing, or if parsing its value returns an error, then the default value must be used instead. The width attribute defaults to 300, and the height attribute defaults to 150.

Emphasis added.

In your case, since the first element, #trail, doesn't have a width or height attribute, the attribute values default to width="300" height="150", which is why you're seeing a difference.

In essence, the width/height attributes set the intrinsic dimensions of the canvas's coordinate space, whereas the CSS properties set the actual size of the canvas element:

The intrinsic dimensions of the canvas element equal the size of the coordinate space, with the numbers interpreted in CSS pixels. However, the element can be sized arbitrarily by a style sheet. During rendering, the image is scaled to fit this layout size.

Therefore if you gave the canvas element the attributes width="100" height="100", then set a CSS width of 100%, the image would be scaled to fit the layout while maintaining the aspect ratio (example).

Community
  • 1
  • 1
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
2

The height and width attributes define the intrinsic size of the canvas (the coordinate space). By default, it will also be rendered at that size.

If you change the CSS width and height, the canvas will be rendered at that new size, but the coordinate space will not change. So the same contents will be scaled to fit the rendered size of the canvas.

CupawnTae
  • 14,192
  • 3
  • 29
  • 60