ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

javascript – 画布中的真实鼠标位置

2019-09-11 06:35:13  阅读:244  来源: 互联网

标签:mouse-position javascript canvas html5-canvas


参见英文答案 > How do I get the coordinates of a mouse click on a canvas element?                                    22个
我试图用鼠标画在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 onm ousemove="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
    };
}

只需使用事件和画布作为参数从事件中调用它.它返回一个带有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);
}

Fiddle with modifications

注意:如果直接应用于canvas元素,则border和padding将影响位置,因此需要通过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
  }
}

Fiddle using scale

将变换应用于上下文(比例,旋转等)

然后有一个更复杂的情况,你已经将变换应用于上下文,如旋转,倾斜/剪切,缩放,平移等.为了解决这个问题,你可以计算当前矩阵的逆矩阵.

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

但在大多数情况下,您必须实现自己的自定义矩阵解决方案(例如我自己的解决方案here – free / 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);
}

Example using the solution linked above(在更广泛支持时替换为本机浏览器解决方案).

实现时使用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找到,并且还可以处理其他一些最容易忽视的细节.

标签:mouse-position,javascript,canvas,html5-canvas
来源: https://codeday.me/bug/20190911/1804082.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有