This question already has answers here:
How do I get the coordinates of a mouse click on a canvas element?
(22个答案)
在11个月前关闭。
我正在尝试用鼠标在HTML5画布上绘制,但是似乎正常工作的唯一方法是,如果出于某种原因,如果我更改了画布位置,那么画布是否位于0,0(左上角)的位置它的绘制效果不理想。这是我的代码。
HTML部分
我已经读过一种方法可以在JavaScript中创建一个简单的函数来获得正确的位置,但是我不知道该怎么做。
只需从事件中调用它,并以事件和画布作为参数即可。它返回一个带有x和y的鼠标位置的对象。
由于您获得的鼠标位置是相对于客户端窗口的,因此您必须减去canvas元素的位置才能将其相对于元素本身进行转换。
代码集成示例:
注意:如果将边框和填充直接应用于canvas元素,则会影响位置,因此需要通过
当元素和位图的大小不同时
例如,当元素的大小与位图本身的大小不同时,可以使用CSS缩放元素,或者存在像素长宽比等。您必须解决这个问题。
例:
将转换应用于上下文(缩放,旋转等)
然后是更为复杂的情况,其中您已对上下文应用了变换,例如旋转,倾斜/剪切,缩放,平移等。要解决此问题,可以计算当前矩阵的逆矩阵。
较新的浏览器使您可以通过
但是,在大多数情况下,您将必须实施自己的自定义矩阵解决方案(例如我自己的解决方案here-free / MIT项目),直到获得完全支持。
当最终获得矩阵时,无论获取矩阵的路径如何,都需要将其反转并将其应用于鼠标坐标。然后将坐标传递到画布,画布将使用其矩阵将其转换回当前位置。
这样,该点将相对于鼠标处于正确的位置。同样在这里,您需要调整坐标(在对它们应用逆矩阵之前),使其相对于元素。
一个仅显示矩阵步骤的示例
在实施时使用
更新我制作了一个免费的解决方案(MIT),将所有这些步骤嵌入到一个易于使用的对象中,该对象可以在here中找到,并且还处理了其他一些最容易被忽略的实质性问题。
(22个答案)
在11个月前关闭。
我正在尝试用鼠标在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方案
对于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);
}
注意:如果将边框和填充直接应用于canvas元素,则会影响位置,因此需要通过
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
。但是,在大多数情况下,您将必须实施自己的自定义矩阵解决方案(例如我自己的解决方案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);
}
在实施时使用
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中找到,并且还处理了其他一些最容易被忽略的实质性问题。