Get canvas click coordinates with css scaling and contain:fit

Viewed 177

For my pixel art website, I have a canvas that is fixed relative to the viewport, scaled with css, and has object-fit:contain; to keep it the size of the div, no matter what is drawn or resized inside. I need to get the mouse click coordinates without scaling. The scaled coordinates collected by e.y/e.x wouldn't be useful since object-fit:contain; would change aspect ratios.

Here is some dummy code to better explain my question:

var c = document.getElementById("scaledCanvas");
var ctx = c.getContext('2d');

c.height = 16; // varaible height
c.width = 16; // varaible width

for (var x = 0; x < c.width; x++) {
  for (var y = 0; y < c.height; y++) {
    ctx.fillStyle = "#" + Math.floor(Math.random() * 16777215).toString(16); // pick random color
    ctx.fillRect(x, y, 1, 1); // draw pixel on canvas
  }
}


c.addEventListener('click', function(e) {
  //this is what i need help with, clickX and clickY need to give the pixel coordinates of the canvas, not the screen
  let clickX = e.x - this.offsetLeft;
  let clickY = e.y - this.offsetTop;

  console.log(clickX + ", " + clickY);
}, false);
#scaledCanvas {
  width: 50vw;
  height: 50vh;
  image-rendering: pixelated;
  object-fit: contain;
  background-color: black;
}
<!DOCTYPE html>
<html>

<body>
  <canvas id="scaledCanvas" width="16" height="16">Canvas Not Supported</canvas>
</body>

</html>

1 Answers

Should it be something like that? I take the "pixel's" cell coords.

var c = document.getElementById("scaledCanvas");
var ctx = c.getContext('2d');

c.height = 16; // varaible height
c.width = 16; // varaible width

for (var x = 0; x < c.width; x++) {
  for (var y = 0; y < c.height; y++) {
    ctx.fillStyle = "#" + Math.floor(Math.random() * 16777215).toString(16); // pick random color
    ctx.fillRect(x, y, 1, 1); // draw pixel on canvas
  }
}


c.addEventListener('click', function(e) {

  let realWidth = c.getBoundingClientRect().width;
  let realHeight = c.getBoundingClientRect().height;

  let cellSize = (realWidth < realHeight) ? realWidth/16 : realHeight/16;

  let clickX = Math.floor((e.x - this.offsetLeft - (realWidth - cellSize*16)/2)/cellSize);
  let clickY = Math.floor((e.y - this.offsetTop - (realHeight - cellSize*16)/2)/cellSize);

  console.log(clickX + ", " + clickY);
}, false);
#scaledCanvas {
  width: 50vw;
  height: 50vh;
  image-rendering: pixelated;
  object-fit: contain;
  background-color: black;
}
<canvas id="scaledCanvas" width="16" height="16">Canvas Not Supported</canvas>

Related