首先,我知道这个问题已被多次询问过.但是,提供的答案并不一致,并且使用各种方法来获得鼠标位置.几个例子:
方法1:
canvas.onmousemove = function (event) { // this object refers to canvas object
Mouse = {
x: event.pageX - this.offsetLeft,
y: event.pageY - this.offsetTop
}
}
方法2:
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
方法3:
var findPos = function(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return { x : curleft, y : curtop };
};
方法4:
var x;
var y;
if (e.pageX || e.pageY)
{
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;
等等.
我很好奇的是哪种方法在浏览器支持方面最为现代,并且在画布中获得鼠标位置方便.或者是那些具有边际影响的东西,上述任何一种都是不错的选择? (是的,我意识到上面的代码并不完全相同)
解决方法:
这似乎有效.我认为这基本上就是K3N所说的.
function getRelativeMousePosition(event, target) {
target = target || event.target;
var rect = target.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
}
}
function getStyleSize(style, propName) {
return parseInt(style.getPropertyValue(propName));
}
// assumes target or event.target is canvas
function getCanvasRelativeMousePosition(event, target) {
target = target || event.target;
var pos = getRelativeMousePosition(event, target);
// you can remove this if padding is 0.
// I hope this always returns "px"
var style = window.getComputedStyle(target);
var nonContentWidthLeft = getStyleSize(style, "padding-left") +
getStyleSize(style, "border-left");
var nonContentWidthTop = getStyleSize(style, "padding-top") +
getStyleSize(style, "border-top");
var nonContentWidthRight = getStyleSize(style, "padding-right") +
getStyleSize(style, "border-right");
var nonContentWidthBottom = getStyleSize(style, "padding-bottom") +
getStyleSize(style, "border-bottom");
var rect = target.getBoundingClientRect();
var contentDisplayWidth = rect.width - nonContentWidthLeft - nonContentWidthRight;
var contentDisplayHeight = rect.height - nonContentWidthTop - nonContentWidthBottom;
pos.x = (pos.x - nonContentWidthLeft) * target.width / contentDisplayWidth;
pos.y = (pos.y - nonContentWidthTop ) * target.height / contentDisplayHeight;
return pos;
}
如果您运行下面的示例并将鼠标移到蓝色区域上,它将在光标下绘制.边框(黑色),填充(红色),宽度和高度都设置为非像素值.蓝色区域是实际的画布像素.画布的分辨率未设置为300×150,无论其拉伸的大小如何.
将鼠标移到蓝色区域,它将在其下方绘制一个像素.
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
function clearCanvas() {
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
clearCanvas();
var posNode = document.createTextNode("");
document.querySelector("#position").appendChild(posNode);
function getRelativeMousePosition(event, target) {
target = target || event.target;
var rect = target.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
}
}
function getStyleSize(style, propName) {
return parseInt(style.getPropertyValue(propName));
}
// assumes target or event.target is canvas
function getCanvasRelativeMousePosition(event, target) {
target = target || event.target;
var pos = getRelativeMousePosition(event, target);
// you can remove this if padding is 0.
// I hope this always returns "px"
var style = window.getComputedStyle(target);
var nonContentWidthLeft = getStyleSize(style, "padding-left") +
getStyleSize(style, "border-left");
var nonContentWidthTop = getStyleSize(style, "padding-top") +
getStyleSize(style, "border-top");
var nonContentWidthRight = getStyleSize(style, "padding-right") +
getStyleSize(style, "border-right");
var nonContentWidthBottom = getStyleSize(style, "padding-bottom") +
getStyleSize(style, "border-bottom");
var rect = target.getBoundingClientRect();
var contentDisplayWidth = rect.width - nonContentWidthLeft - nonContentWidthRight;
var contentDisplayHeight = rect.height - nonContentWidthTop - nonContentWidthBottom;
pos.x = (pos.x - nonContentWidthLeft) * target.width / contentDisplayWidth;
pos.y = (pos.y - nonContentWidthTop ) * target.height / contentDisplayHeight;
return pos;
}
function handleMouseEvent(event) {
var pos = getCanvasRelativeMousePosition(event);
posNode.nodeValue = JSON.stringify(pos, null, 2);
ctx.fillStyle = "white";
ctx.fillRect(pos.x | 0, pos.y | 0, 1, 1);
}
canvas.addEventListener('mousemove', handleMouseEvent);
canvas.addEventListener('click', clearCanvas);
* {
box-sizing: border-box;
cursor: crosshair;
}
html, body {
width: 100%;
height: 100%;
color: white;
}
.outer {
background-color: green;
display: flex;
display: -webkit-flex;
-webkit-justify-content: center;
-webkit-align-content: center;
-webkit-align-items: center;
justify-content: center;
align-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.inner {
border: 1em solid black;
background-color: red;
padding: 1.5em;
width: 90%;
height: 90%;
}
#position {
position: absolute;
left: 1em;
top: 1em;
z-index: 2;
pointer-events: none;
}
<div class="outer">
<canvas class="inner"></canvas>
</div>
<pre id="position"></pre>
那么,最好的建议?,除非你想要完成所有这些步骤,否则总是将画布的边框和填充为0.如果边框和填充为零,则可以在下面的示例中对contentDisplayWidth和contentDisplayHeight使用canvas.clientWidth和canvas.clientHeight,并且所有nonContextXXX值都将变为0.
function getRelativeMousePosition(event, target) {
target = target || event.target;
var rect = target.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
}
}
// assumes target or event.target is canvas
function getNoPaddingNoBorderCanvasRelativeMousePosition(event, target) {
target = target || event.target;
var pos = getRelativeMousePosition(event, target);
pos.x = pos.x * target.width / canvas.clientWidth;
pos.y = pos.y * target.height / canvas.clientHeight;
return pos;
}
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
function clearCanvas() {
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
clearCanvas();
var posNode = document.createTextNode("");
document.querySelector("#position").appendChild(posNode);
function getRelativeMousePosition(event, target) {
target = target || event.target;
var rect = target.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top,
}
}
// assumes target or event.target is canvas
function getNoPaddingNoBorderCanvasRelativeMousePosition(event, target) {
target = target || event.target;
var pos = getRelativeMousePosition(event, target);
pos.x = pos.x * target.width / canvas.clientWidth;
pos.y = pos.y * target.height / canvas.clientHeight;
return pos;
}
function handleMouseEvent(event) {
var pos = getNoPaddingNoBorderCanvasRelativeMousePosition(event);
posNode.nodeValue = JSON.stringify(pos, null, 2);
ctx.fillStyle = "white";
ctx.fillRect(pos.x | 0, pos.y | 0, 1, 1);
}
canvas.addEventListener('mousemove', handleMouseEvent);
canvas.addEventListener('click', clearCanvas);
* {
box-sizing: border-box;
cursor: crosshair;
}
html, body {
width: 100%;
height: 100%;
color: white;
}
.outer {
background-color: green;
display: flex;
display: -webkit-flex;
-webkit-justify-content: center;
-webkit-align-content: center;
-webkit-align-items: center;
justify-content: center;
align-content: center;
align-items: center;
width: 100%;
height: 100%;
}
.inner {
background-color: red;
width: 90%;
height: 80%;
display: block;
}
#position {
position: absolute;
left: 1em;
top: 1em;
z-index: 2;
pointer-events: none;
}
<div class="outer">
<canvas class="inner"></canvas>
</div>
<pre id="position"></pre>