2

I've a hard problem to describe/present, because this part of code is deeply inside my Angular app.

Anyway, I have a div 350px x 350px and I would cover it by canvas, and draw a line on it.

What I did? I created a canvas tag before the table and apply this CSS rules:

canvas{
  position: absolute;
  width: 350px;
  height: 350px;
  border: dotted black 2px; <-- only for visual effect
}

It covered div.

Next I tried to draw a simple line to test it (I missed here part of code which download reference to canvas, because it works):

const ctx = canvasNativeEl.getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stroke();

I expected to get a diagonal of square. Unfortunately I got diagonal of rectangle, like this:

enter image description here

This problem doesn't allow me to draw a target line, because coordinates are wrong.

If You have any ideas I would gladly see it. Regards!

3D_fun
  • 553
  • 1
  • 4
  • 17

1 Answers1

3

As I explained in a previous question The issue is that using width/height properties on canvas will create a scale effect. Here is a before/after to better see your issue:

canvasNativeEl = document.querySelectorAll('canvas');

let ctx = canvasNativeEl[0].getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stroke();

ctx = canvasNativeEl[1].getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stroke();
canvas{
  border: dotted black 2px;
}
<canvas></canvas>
<canvas style="width: 350px;height: 350px;"></canvas>

As you can see, the second canvas is a scaled version of the first one. It's like we correctly draw our line considering the first one then after that we change width/height to obtain the second one.

In order to avoid this you should consider height/width attribute to have correct coordinates and avoid the scaling effect

canvasNativeEl = document.querySelectorAll('canvas');

let ctx = canvasNativeEl[0].getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stroke();

ctx = canvasNativeEl[1].getContext('2d');
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stroke();
canvas{
  border: dotted black 2px;
}
<canvas></canvas>
<canvas width='350' height="350" ></canvas>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • So, solution is to put size in HTML tag instead using CSS? – 3D_fun Dec 04 '18 at 09:17
  • @3D_fun exactly, in order to have the correct coordinate – Temani Afif Dec 04 '18 at 09:19
  • It works. Do You know why using width/height attributes works instead CSS styles? – 3D_fun Dec 04 '18 at 09:19
  • @3D_fun because height/width attribute will define the width/height properties of the canvas and will preserve the coordinate .. Using CSS you will simply scale the canvas, it's like you adjust the width/height of an image, somites you distort it because you don't keep the good ratio (you can check the linked question in my answer for more accurate explanation) – Temani Afif Dec 04 '18 at 09:22