Skip to content Skip to sidebar Skip to footer

Get Canvas Mouse Coordinates After Transformation Using Ctx.gettransformation()

I am using the following function to get mouse coordinates on canvas after performing rotations. function getWindowToCanvas(canvas, x, y) { const ctx = canvas.getContext('2d');

Solution 1:

Thanks to @MarkusJarderot and jsFiddle getting mouse coordinates from un-rotated canvas I was able to get a solution that is close to perfect. I don't quite understand it, but it works much better.

functiongetWindowToCanvas(canvas, e) {

 //first calculate normal mouse coordinates
  e = e || window.event;
  var target = e.target || e.srcElement,
    style = target.currentStyle || window.getComputedStyle(target, null),
    borderLeftWidth = parseInt(style["borderLeftWidth"], 10),
    borderTopWidth = parseInt(style["borderTopWidth"], 10),
    rect = target.getBoundingClientRect(),
    offsetX = e.clientX - borderLeftWidth - rect.left,
    offsetY = e.clientY - borderTopWidth - rect.top;
  let x = (offsetX * target.width) / target.clientWidth;
  let y = (offsetY * target.height) / target.clientHeight;

  //then adjust coordinates for the context's transformationsconst ctx = canvas.getContext("2d");
  var transform = ctx.getTransform();
  const invMat = transform.invertSelf();
  return {
    x: x * invMat.a + y * invMat.c + invMat.e,
    y: x * invMat.b + y * invMat.d + invMat.f
  };
}

The only issue remaining is that, when rotated say 45deg, drawing a rectangle with ctx.rect() draws a rectangle that parallels with respect to the canvas, not to the window, so the rectangle is slanted even though it is finally in the right place. I want to draw rectangles with respect to the window, not the canvas. However, this may just be how ctx.rect() works, and I'll need to update later. For now, this could help others.

UPDATEFigured out original bug. Since I didn't understand why my original function was not working, used the above solution to start trouble-shooting it. It turns out that the reason the above code did not work is because I was calling console.log(transform.invertSelf()) to see the transform while I was debugging. This mutated the transform. So, when I called var invMat = transform.invertSelf() right after, I inverted it yet again! I should have paid attention to the 'self' in 'invertSelf'.

This function now works

functiongetWindowToCanvas(canvas, x, y) {
  var rect = canvas.getBoundingClientRect();
  var screenX = (x - rect.left) * (canvas.width / rect.width);
  var screenY = (y - rect.top) * (canvas.height / rect.height);
  const ctx = canvas.getContext("2d");
  var transform = ctx.getTransform();
  if (transform.isIdentity) {
    return {
      x: screenX,
      y: screenY
    };
  } else {
    //   console.log(transform.invertSelf()); //don't invert twice!!const invMat = transform.invertSelf();

    return {
      x: Math.round(screenX * invMat.a + screenY * invMat.c + invMat.e),
      y: Math.round(screenX * invMat.b + screenY * invMat.d + invMat.f)
    };
  }
}

Post a Comment for "Get Canvas Mouse Coordinates After Transformation Using Ctx.gettransformation()"