javascript - Canvas 中的真实鼠标位置

标签 javascript canvas html5-canvas mouse-position

我试图用鼠标在 HTML5 Canvas 上绘制,但它似乎工作良好的唯一方法是如果我更改 Canvas 位置, Canvas 位于位置 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 场景

对于 Canvas 元素与位图大小的比例为 1:1 的情况,您可以使用以下代码片段获取鼠标位置:

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}

只需使用事件和 Canvas 作为参数从您的事件中调用它。它返回一个包含鼠标位置的 xy 的对象。

由于您获得的鼠标位置是相对于客户端窗口的,因此您必须减去 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);
}

注意:如果直接应用于 Canvas 元素,边框和内边距会影响位置,因此需要通过 getComputedStyle() 来考虑这些 - 或者将这些样式应用于父元素div 代替。

当Element和Bitmap大小不同时

当元素的大小与位图本身的大小不同时,例如,使用 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

然而,在大多数情况下,您必须实现自己的自定义矩阵解决方案(例如我自己的解决方案 here – 免费/麻省理工学院项目),直到获得全面支持。

当您最终获得矩阵时,无论您采用何种路径获得矩阵,您都需要将其反转并将其应用于您的鼠标坐标。然后将坐标传递给 Canvas , Canvas 将使用其矩阵将其转换为当前位置的坐标。

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

仅显示矩阵步骤的示例:

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),将所有这些步骤嵌入到一个易于使用的对象中,该对象可以在 here 中找到。并且还处理其他一些最被忽视的细节问题。

关于javascript - Canvas 中的真实鼠标位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17130395/

相关文章:

javascript - typescript Canvas

jquery - 应用 css 后保存 Canvas /图像

javascript - Canvas 中一张图像上的 globalAlpha

javascript - 如果 $.post() 之后有重定向,则 $.post() 不起作用 : window. location.href =

Javascript:需要表单在提交后从所有网站页面消失

javascript - jQuery 多个 animate() 回调

javascript - Threejs,div innerWidth 和innerHeight 设置平面的宽度和高度后会自行改变吗?

javascript - 如何从另一种颜色中减去一种颜色

javascript - 设置iframe的内容

html - 为什么 HTML 5 Canvas 中的矩形不是黑色?