Javascript 画布中鼠标的真实位置

Javascript 画布中鼠标的真实位置,javascript,canvas,html5-canvas,mouse-position,Javascript,Canvas,Html5 Canvas,Mouse Position,我试图用鼠标在HTML5画布上画图,但唯一有效的方法是,如果画布处于0,0(左上角)的位置,如果我改变画布位置,出于某种原因,它不会像应该的那样画图。这是我的密码 function createImageOnCanvas(imageId){ document.getElementById("imgCanvas").style.display = "block"; document.getElementById("images").style.overflowY= "hidden

我试图用鼠标在HTML5画布上画图,但唯一有效的方法是,如果画布处于0,0(左上角)的位置,如果我改变画布位置,出于某种原因,它不会像应该的那样画图。这是我的密码

 function createImageOnCanvas(imageId){
    document.getElementById("imgCanvas").style.display = "block";
    document.getElementById("images").style.overflowY= "hidden";
    var canvas = document.getElementById("imgCanvas");
    var context = canvas.getContext("2d");
    var img = new Image(300,300);
    img.src = document.getElementById(imageId).src;
    context.drawImage(img, (0),(0));
}

function draw(e){
    var canvas = document.getElementById("imgCanvas");
    var context = canvas.getContext("2d");
    posx = e.clientX;
    posy = e.clientY;
    context.fillStyle = "#000000";
    context.fillRect (posx, posy, 4, 4);
}
HTML部分

 <body>
 <div id="images">
 </div>
 <canvas onmousemove="draw(event)" style="margin:0;padding:0;" id="imgCanvas"
          class="canvasView" width="250" height="250"></canvas> 

我读过有一种方法可以用JavaScript创建一个简单的函数来获得正确的位置,但我不知道如何做到这一点

简单的1:1场景 对于画布元素与位图大小之比为1:1的情况,可以使用以下代码段获取鼠标位置:

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
}
function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: (evt.clientX - rect.left) / (rect.right - rect.left) * canvas.width,
        y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * canvas.height
    };
}
只需使用事件和画布作为参数从事件中调用它。它返回一个对象,其中x和y代表鼠标位置

由于您获得的鼠标位置是相对于客户端窗口的,因此必须减去canvas元素的位置,才能将其转换为相对于元素本身的位置

代码中的集成示例:

//put this outside the event loop..
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");

function draw(evt) {
    var pos = getMousePos(canvas, evt);

    context.fillStyle = "#000000";
    context.fillRect (pos.x, pos.y, 4, 4);
}
注意:如果直接应用于画布元素,边框和填充将影响位置,因此需要通过
getComputedStyle()
-或将这些样式应用于父div

当元素和位图的大小不同时 当元素的大小与位图本身不同时,例如,使用CSS缩放元素或存在像素纵横比等。您必须解决此问题

示例:

function  getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect(), // abs. size of element
      scaleX = canvas.width / rect.width,    // relationship bitmap vs. element for X
      scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for Y

  return {
    x: (evt.clientX - rect.left) * scaleX,   // scale mouse coordinates after they have
    y: (evt.clientY - rect.top) * scaleY     // been adjusted to be relative to element
  }
}
将变换应用于上下文(缩放、旋转等) 还有一种更复杂的情况,您将变换应用于上下文,例如旋转、倾斜/剪切、缩放、平移等。要处理此问题,您可以计算当前矩阵的逆矩阵

较新的浏览器允许您通过
currentTransform
属性读取当前矩阵,Firefox(当前alpha)甚至通过
mozCurrentTransformInverted
提供反转矩阵。然而,Firefox通过
mozCurrentTransform
,将返回一个数组,而不是
DOMMatrix
。当通过实验标志启用时,Chrome都不会返回
DOMMatrix
,而是返回
SVGMatrix

然而,在大多数情况下,您必须实现自己的定制矩阵解决方案(例如我自己的无解决方案/MIT项目),直到获得完全支持为止

当您最终获得矩阵时,不管您采用何种路径获得矩阵,您都需要将其反转并将其应用于鼠标坐标。然后坐标被传递到画布,画布将使用其矩阵将其转换回当前所在的位置

这样,点将位于相对于鼠标的正确位置。这里还需要调整坐标(在对坐标应用逆矩阵之前),使其相对于元素

仅显示矩阵步骤的示例

function draw(evt) {
    var pos = getMousePos(canvas, evt);        // get adjusted coordinates as above
    var imatrix = matrix.inverse();            // get inverted matrix somehow
    pos = imatrix.applyToPoint(pos.x, pos.y);  // apply to adjusted coordinate

    context.fillStyle = "#000000";
    context.fillRect(pos.x-1, pos.y-1, 2, 2);
}
实施时使用
currentTransform
的示例如下:

    var pos = getMousePos(canvas, e);          // get adjusted coordinates as above
    var matrix = ctx.currentTransform;         // W3C (future)
    var imatrix = matrix.invertSelf();         // invert

    // apply to point:
    var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e;
    var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f;
更新我制作了一个免费解决方案(MIT),将所有这些步骤嵌入到一个简单易用的对象中,该对象可以找到,并且还可以处理一些其他大多数人忽略的基本问题。

简单的1:1场景 对于画布元素与位图大小之比为1:1的情况,可以使用以下代码段获取鼠标位置:

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
}
function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: (evt.clientX - rect.left) / (rect.right - rect.left) * canvas.width,
        y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * canvas.height
    };
}
只需使用事件和画布作为参数从事件中调用它。它返回一个对象,其中x和y代表鼠标位置

由于您获得的鼠标位置是相对于客户端窗口的,因此必须减去canvas元素的位置,才能将其转换为相对于元素本身的位置

代码中的集成示例:

//put this outside the event loop..
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");

function draw(evt) {
    var pos = getMousePos(canvas, evt);

    context.fillStyle = "#000000";
    context.fillRect (pos.x, pos.y, 4, 4);
}
注意:如果直接应用于画布元素,边框和填充将影响位置,因此需要通过
getComputedStyle()
-或将这些样式应用于父div

当元素和位图的大小不同时 当元素的大小与位图本身不同时,例如,使用CSS缩放元素或存在像素纵横比等。您必须解决此问题

示例:

function  getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect(), // abs. size of element
      scaleX = canvas.width / rect.width,    // relationship bitmap vs. element for X
      scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for Y

  return {
    x: (evt.clientX - rect.left) * scaleX,   // scale mouse coordinates after they have
    y: (evt.clientY - rect.top) * scaleY     // been adjusted to be relative to element
  }
}
将变换应用于上下文(缩放、旋转等) 还有一种更复杂的情况,您将变换应用于上下文,例如旋转、倾斜/剪切、缩放、平移等。要处理此问题,您可以计算当前矩阵的逆矩阵

较新的浏览器允许您通过
currentTransform
属性读取当前矩阵,Firefox(当前alpha)甚至通过
mozCurrentTransformInverted
提供反转矩阵。然而,Firefox通过
mozCurrentTransform
,将返回一个数组,而不是
DOMMatrix
。当通过实验标志启用时,Chrome都不会返回
DOMMatrix
,而是返回
SVGMatrix

然而,在大多数情况下,您必须实现自己的定制矩阵解决方案(例如我自己的无解决方案/MIT项目),直到获得完全支持为止

当您最终获得矩阵时,不管您采用何种路径获得矩阵,您都需要将其反转并将其应用于鼠标坐标。然后坐标被传递到画布,画布将使用其矩阵将其转换回当前所在的位置

这样,点将位于相对于鼠标的正确位置。这里还需要调整坐标(在对坐标应用逆矩阵之前),使其相对于元素

仅显示矩阵步骤的示例

function draw(evt) {
    var pos = getMousePos(canvas, evt);        // get adjusted coordinates as above
    var imatrix = matrix.inverse();            // get inverted matrix somehow
    pos = imatrix.applyToPoint(pos.x, pos.y);  // apply to adjusted coordinate

    context.fillStyle = "#000000";
    context.fillRect(pos.x-1, pos.y-1, 2, 2);
}
实施时使用
currentTransform
的示例如下:

    var pos = getMousePos(canvas, e);          // get adjusted coordinates as above
    var matrix = ctx.currentTransform;         // W3C (future)
    var imatrix = matrix.invertSelf();         // invert

    // apply to point:
    var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e;
    var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f;
更新我制作了一个免费解决方案(MIT),将所有这些步骤嵌入到一个简单易用的对象中,该对象可以找到,还可以处理其他一些步骤