使用ctx.getTransformation()进行转换后获取画布鼠标坐标 [英] get canvas mouse coordinates after transformation using ctx.getTransformation()

查看:191
本文介绍了使用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");
  var transform = ctx.getTransform();
  var rect = canvas.getBoundingClientRect();
  var screenX = (x - rect.left) * (canvas.width / rect.width);
  var screenY = (y - rect.top) * (canvas.height / rect.height);

  if (transform.isIdentity) {
    return {
      x: screenX,
      y: screenY
    };
  } else {
    console.log(transform.invertSelf());
    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)
    };
  }
}

在阅读 html5-canvas之后,我使用了逆变换矩阵-transformation-algorithm 最佳-将鼠标坐标转换为html5-画布转换后的上下文

我让用户用鼠标绘制矩形,转换后需要获得鼠标的x,y坐标,但是一旦画布旋转(例如旋转90度),则矩形不再跟随鼠标指针.

I am letting the user draw rectangles with the mouse, and I need to get the mouse x,y coordinates after transformations, but once the canvas is rotated (say by 90 deg) then the rectangles no longer follow the mouse pointer.

有人知道我在做什么吗?

Does anyone know what I'm doing wrong?

推荐答案

感谢@MarkusJarderot和 jsFiddle从鼠标坐标中获取未旋转的画布我能够得到一个 close 完美的解决方案.我不太了解,但是效果更好.

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.

function getWindowToCanvas(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 transformations
  const 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
  };
}

剩下的唯一问题是,当旋转45度时,使用ctx.rect()绘制一个矩形会绘制一个相对于画布(而不是窗口)平行的矩形,因此即使最终矩形仍会倾斜在正确的地方.我想相对于窗口而不是画布绘制矩形.但是,这可能只是ctx.rect()的工作方式,以后需要更新.目前,这可以帮助其他人.

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.

更新 找出原始错误. 由于我不明白为什么我的原始功能无法正常工作,因此使用上述解决方案开始对其进行故障排除.原来,上面的代码不起作用的原因是因为我在调试时调用console.log(transform.invertSelf())来查看转换.这使变换发生了变化.因此,当我之后立即调用var invMat = transform.invertSelf()时,我又将其反转了!我应该注意"invertSelf"中的自我".

UPDATE Figured 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'.

此功能现在可用

function getWindowToCanvas(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)
    };
  }
}

这篇关于使用ctx.getTransformation()进行转换后获取画布鼠标坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆