画布中的真实鼠标位置 [英] Real mouse position in canvas

查看:30
本文介绍了画布中的真实鼠标位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用鼠标在 HTML5 画布上绘图,但它似乎工作良好的唯一方法是如果我更改画布位置,画布是否位于位置 0,0(左上角),出于某种原因,它没有像它应该的那样绘制.这是我的代码.

 函数 createImageOnCanvas(imageId){document.getElementById("imgCanvas").style.display = "block";document.getElementById("images").style.overflowY="隐藏";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));}函数绘制(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 部分

 <div id="图像">

<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();返回 {x: evt.clientX - rect.left,y: evt.clientY - rect.top};}

只需使用事件和画布作为参数从您的事件中调用它.它返回一个带有 x 和 y 的对象作为鼠标位置.

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

代码中的集成示例:

//把它放在事件循环之外..var canvas = document.getElementById("imgCanvas");var context = canvas.getContext("2d");函数绘制(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.元素的大小scaleX = canvas.width/rect.width,//位图与 X 元素的关系scaleY = canvas.height/rect.height;//关系位图 vs. Y 的元素返回 {x: (evt.clientX - rect.left) * scaleX,//缩放鼠标坐标后y: (evt.clientY - rect.top) * scaleY//被调整为相对于元素}}

将变换应用于上下文(缩放、旋转等)

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

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

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

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

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

仅显示矩阵步骤的示例

function draw(evt) {var pos = getMousePos(canvas, evt);//获取如上调整后的坐标var imatrix = matrix.inverse();//以某种方式获得逆矩阵pos = imatrix.applyToPoint(pos.x, pos.y);//应用于调整后的坐标context.fillStyle = "#000000";context.fillRect(pos.x-1, pos.y-1, 2, 2);}

在实施时使用 currentTransform 的一个例子是:

 var pos = getMousePos(canvas, e);//获取如上调整后的坐标var 矩阵 = ctx.currentTransform;//W3C(未来)var imatrix = matrix.invertSelf();//反转//适用于点: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) 将所有这些步骤嵌入到一个易于使用的对象中,该对象可以在 此处 并且还处理了其他一些最容易被忽视的细节.

I'm trying to draw with the mouse over a HTML5 canvas, but the only way that it seems to work well is if the canvas is in the position 0,0 (upper left corner) if I change the canvas position, for some reason it doesn't draw like it should. Here is my code.

 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);
}

The HTML part

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

I have read there's a way of creating a simple function in JavaScript to get the right position, but I have no idea about how to do it.

解决方案

The Simple 1:1 Scenario

For situations where the canvas element is 1:1 compared to the bitmap size, you can get the mouse positions by using this snippet:

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

Just call it from your event with the event and canvas as arguments. It returns an object with x and y for the mouse positions.

As the mouse position you are getting is relative to the client window you'll have to subtract the position of the canvas element to convert it relative to the element itself.

Example of integration in your code:

//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);
}

Note: borders and padding will affect position if applied directly to the canvas element so these needs to be considered via getComputedStyle() - or apply those styles to a parent div instead.

When Element and Bitmap are of different sizes

When there is the situation of having the element at a different size than the bitmap itself, for example, the element is scaled using CSS or there is pixel-aspect ratio etc. you will have to address this.

Example:

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
  }
}

With transformations applied to context (scale, rotation etc.)

Then there is the more complicated case where you have applied transformation to the context such as rotation, skew/shear, scale, translate etc. To deal with this you can calculate the inverse matrix of the current matrix.

Newer browsers let you read the current matrix via the currentTransform property and Firefox (current alpha) even provide a inverted matrix through the mozCurrentTransformInverted. Firefox however, via mozCurrentTransform, will return an Array and not DOMMatrix as it should. Neither Chrome, when enabled via experimental flags, will return a DOMMatrix but a SVGMatrix.

In most cases however you will have to implement a custom matrix solution of your own (such as my own solution here - free/MIT project) until this get full support.

When you eventually have obtained the matrix regardless of path you take to obtain one, you'll need to invert it and apply it to your mouse coordinates. The coordinates are then passed to the canvas which will use its matrix to convert it to back wherever it is at the moment.

This way the point will be in the correct position relative to the mouse. Also here you need to adjust the coordinates (before applying the inverse matrix to them) to be relative to the element.

An example just showing the matrix steps

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);
}

An example of using currentTransform when implemented would be:

    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;

Update I made a free solution (MIT) to embed all these steps into a single easy-to-use object that can be found here and also takes care of a few other nitty-gritty things most ignore.

这篇关于画布中的真实鼠标位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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