如何在转换HTML5画布上获得鼠标位置

How to get Mouse Position on Transformed HTML5 Canvas

本文关键字:鼠标 位置 转换 HTML5      更新时间:2023-09-26

我试图在转换的画布上获得鼠标位置。这是我的调整大小方法:

window.addEventListener('resize', resize);
function resize() {
    screenWidth = window.innerWidth;
    screenHeight = window.innerHeight;
    scaleFillNative = MathMAX(screenWidth / maxScreenWidth, screenHeight / maxScreenHeight);
    mainCanvas.width = screenWidth;
    mainCanvas.height = screenHeight;
    mainContext.setTransform(scaleFillNative, 0, 0, scaleFillNative, Math.floor((screenWidth - (maxScreenWidth * scaleFillNative)) / 2), 
        Math.floor((screenHeight - (maxScreenHeight * scaleFillNative)) / 2));
}

maxScreenWidth和maxScreenHeight表示画布应该转换为的本机屏幕尺寸。

实际的大小调整工作良好。然而问题是,我试图在画布上的鼠标位置渲染一个圆圈。鼠标位置设置如下:

window.addEventListener('mousemove', gameInput, false);
var mouseX, mouseY;
function gameInput(e) {
    e.preventDefault();
    e.stopPropagation();
    mouseX = e.clientX;
    mouseY = e.clientY;
}

然后呈现如下:

renderCircle(mouseX / scaleFillNative, mouseY / scaleFillNative, 10);

正确呈现x位置。但是,当我调整窗口的大小使宽度小于高度时,它不再在正确的x位置呈现。y的位置总是偏移的。

我不知道你到底尝试了什么,但对于一个基本的鼠标坐标转换画布(非倾斜),你必须做

mouseX = (evt.clientX - canvas.offsetLeft - translateX) / scaleX;
mouseY = (evt.clientY - canvas.offsetTop - translateY) / scaleY;

但是canvas.offsetXXX没有考虑滚动量,所以这个演示使用getBoundingRect代替。

var ctx = canvas.getContext('2d');
window.addEventListener('resize', resize);
// you probably have these somewhere
var maxScreenWidth = 1800,
  maxScreenHeight = 1200,
  scaleFillNative, screenWidth, screenHeight;
// you need to set available to your mouse move listener
var translateX, translateY;
function resize() {
  screenWidth = window.innerWidth;
  screenHeight = window.innerHeight;
  // here you set scaleX and scaleY to the same variable
  scaleFillNative = Math.max(screenWidth / maxScreenWidth, screenHeight / maxScreenHeight);
  canvas.width = screenWidth;
  canvas.height = screenHeight;
  // store these values
  translateX = Math.floor((screenWidth - (maxScreenWidth * scaleFillNative)) / 2);
  translateY = Math.floor((screenHeight - (maxScreenHeight * scaleFillNative)) / 2);
  ctx.setTransform(scaleFillNative, 0, 0, scaleFillNative, translateX, translateY);
}
window.addEventListener('mousemove', mousemoveHandler, false);
function mousemoveHandler(e) {
  // Note : I don't think there is any event default on mousemove, no need to prevent it
  // normalize our event's coordinates to the canvas current transform
  // here we use .getBoundingRect() instead of .offsetXXX 
  //   because we also need to take scroll into account,
  //   in production, store it on debounced(resize + scroll) events.
  var rect = canvas.getBoundingClientRect();
  var mouseX = (e.clientX - rect.left - translateX) / scaleFillNative,
    mouseY = (e.clientY - rect.top - translateY) / scaleFillNative;
  ctx.fillRect(mouseX - 5, mouseY - 5, 10, 10);
}
// an initial call
resize();
<canvas id="canvas"></canvas>