简单的1:1场景
对于画布元素与位图大小相等的情况,您可以使用以下代码片段来获取鼠标位置:
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
只需在事件中使用事件和画布作为参数调用它。它返回一个带有鼠标位置 x
和 y
的对象。
由于您获取的鼠标位置是相对于客户端窗口的,因此您需要减去画布元素的位置以将其转换为相对于元素本身的位置。
以下是在您的代码中集成的示例:
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(),
scaleX = canvas.width / rect.width,
scaleY = canvas.height / rect.height;
return {
x: (evt.clientX - rect.left) * scaleX,
y: (evt.clientY - rect.top) * scaleY
}
}
应用于上下文的变换(缩放、旋转等)
然后就有了更复杂的情况,即您已经对上下文应用了变换,例如旋转、倾斜/剪切、缩放、平移等。为了处理这种情况,您可以计算当前矩阵的逆矩阵。
较新的浏览器允许您通过 currentTransform
属性读取当前矩阵,甚至 Firefox(当前 alpha 版本)还通过 mozCurrentTransformInverted
提供了一个反转矩阵。但是,Firefox 通过 mozCurrentTransform
将返回一个数组,而不是应该返回的 DOMMatrix
。启用实验性标志后,Chrome 也不会返回 DOMMatrix
,而是返回 SVGMatrix
。
然而,在大多数情况下,您将不得不实现自己的自定义矩阵解决方案(例如我的解决方案 here - 免费/MIT 项目),直到它得到完全支持。
无论您采取哪种方法获得矩阵,最终都需要获取矩阵并将其反转并应用于鼠标坐标。然后将坐标传递给画布,画布将使用其矩阵将其转换回当前位置。
这样,点就会相对于鼠标处于正确的位置。此外,在应用逆矩阵之前,您需要调整坐标以相对于元素。
以下是一个仅展示矩阵步骤的示例:
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); // 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),将所有这些步骤嵌入到一个易于使用的对象中,可以在 这里找到,并处理大多数忽略的其他琐碎的事情。
var bRect = theCanvas.getBoundingClientRect(); mouseX = (evt.clientX - bRect.left)*(theCanvas.width/bRect.width); mouseY = (evt.clientY - bRect.top)*(theCanvas.height/bRect.height);
在所有浏览器中都可以运行,包括Safari iOS。但在Chrome Android设备中无法正常工作。可能出了什么问题? - Adam