4

Here's my code:

const canv = document.getElementById('canvas');
const ctxt = canv.getContext('2d');
const w = canv.width;
const h = canv.height;
canv.addEventListener('mousemove', e => {
  ctxt.clearRect(0, 0, canvas.width, canvas.height);
  drawLine(e.clientX, 0, e.clientX, h);
  drawLine(0, e.clientY, w, e.clientY);
})
function drawLine(x1, y1, x2, y2) {
  ctxt.beginPath();
  ctxt.moveTo(x1, y1);
  ctxt.lineTo(x2, y2);
  ctxt.stroke();
}
canvas {
  border: 1px solid black;
  width: 100%;
  height: 100%;
}
<canvas id='canvas'></canvas>

e.clientX and e.clientY aren't working accurately (run code). How do I fix this?

pythag0ras_
  • 122
  • 11
  • You can't resize a Canvas with CSS. You can, however, set `canv.width` and `canv.height` in the JavaScript code, like so: `canv.width = 1000;` – Caleb Denio Jan 12 '20 at 18:32
  • Or resize with CSS but then remember to make sure to properly scale your x/y dimensions by looking at the canvas's `getBoundingClientRect` – Mike 'Pomax' Kamermans Jan 12 '20 at 18:33
  • Does this answer your question? [Real mouse position in canvas](https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas) – AndrewL64 Jan 12 '20 at 18:34

2 Answers2

1

First of all, you should not use CSS to set the size of the canvas, you should instead use the attributes width and height.

Secondly, you should use the relative mouse position (relative to the canvas) so that crosshair is accurate. For that we will use code from this other SO answer.

Here is how it should be done:

const canv = document.getElementById('canvas');
const ctxt = canv.getContext('2d');
const w = canv.width;
const h = canv.height;

const rect = canv.getBoundingClientRect();

canv.addEventListener('mousemove', e => {

  const x = e.pageX - rect.left;
  const y = e.pageY - rect.top;

  ctxt.clearRect(0, 0, canvas.width, canvas.height);
  ctxt.beginPath();
  ctxt.moveTo(0, y);
  ctxt.lineTo(w, y);
  ctxt.moveTo(x, 0);
  ctxt.lineTo(x, h);
  ctxt.stroke();
});

/* drawLine is really not necessary */
canvas {
  border: 1px solid black;
  /* no sizing here */
}
<canvas id='canvas' width="640" height="480"></canvas>

Note: Use pageX and pageY instead of clientX and clientY so that if scrolling is involved you'll still get accurate tracking. clientX and clientY don't take scrolling into account whereas pageX and pageY do.

ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
0

You need to scale the mouse position to the real drawing size of the canvas. The css style do not set the size of the drawing area only the size of the html element.

const canv = document.getElementById("canvas");
const ctxt = canv.getContext("2d");

const rect = canv.getBoundingClientRect();

canv.addEventListener("mousemove", e => {

  ctxt.clearRect(0, 0, canvas.width, canvas.height);

  const ex = (e.pageX - rect.left) / canv.offsetWidth * canv.width;
  const ey = (e.pageY - rect.top) / canv.offsetHeight * canv.height;

  drawLine(ex, 0, ex, canv.height);
  drawLine(0, ey, canv.width, ey);

});

function drawLine(x1, y1, x2, y2) {
  ctxt.beginPath();
  ctxt.moveTo(x1, y1);
  ctxt.lineTo(x2, y2);
  ctxt.stroke();
}
canvas {
  border: 1px solid black;
  width: 100px;
  height: 100px;
}
<canvas id='canvas'></canvas>

Without the height and width html attribute default values of width=150 and height=300 will be applied.

iY1NQ
  • 2,308
  • 16
  • 18