【发布时间】:2010-11-10 00:16:19
【问题描述】:
有没有办法在<canvas> 标签中获取位置鼠标?我想要相对于<canvas> 右上角的位置,而不是整个页面。
【问题讨论】:
标签: javascript html canvas
有没有办法在<canvas> 标签中获取位置鼠标?我想要相对于<canvas> 右上角的位置,而不是整个页面。
【问题讨论】:
标签: javascript html canvas
从鼠标位置减去画布 DOM 元素的 X 和 Y 偏移,得到画布内的本地位置。
【讨论】:
最简单的方法大概是给canvas元素添加一个onmousemove事件监听器,然后就可以从事件本身获取相对于canvas的坐标了。
如果您只需要支持特定的浏览器,这很容易实现,但是 f.ex 之间存在差异。歌剧和火狐。
这样的东西应该适用于这两个:
function mouseMove(e)
{
var mouseX, mouseY;
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
/* do something with mouseX/mouseY */
}
【讨论】:
layerX 和layerY 是相对于非定位元素的整个文档。请在此处查看我的答案以获取更多信息:stackoverflow.com/questions/5085689/…
另请注意,您需要 CSS:
位置:相对;
设置为您的画布标签,以获取画布内的相对鼠标位置。
如果有边框,偏移量会发生变化
【讨论】:
e.layerX 和e.layerY 在它是定位元素时相对于画布,但在不是定位元素时相对于整个文档。请注意,这些属性不是任何标准的一部分。有更好的方法来做到这一点。
对于鼠标位置,我通常使用 jQuery,因为它标准化了一些事件属性。
function getPosition(e) {
//this section is from http://www.quirksmode.org/js/events_properties.html
var targ;
if (!e)
e = window.event;
if (e.target)
targ = e.target;
else if (e.srcElement)
targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
// jQuery normalizes the pageX and pageY
// pageX,Y are the mouse positions relative to the document
// offset() returns the position of the element relative to the document
var x = e.pageX - $(targ).offset().left;
var y = e.pageY - $(targ).offset().top;
return {"x": x, "y": y};
};
// now just make sure you use this with jQuery
// obviously you can use other events other than click
$(elm).click(function(event) {
// jQuery would normalize the event
position = getPosition(event);
//now you can use the x and y positions
alert("X: " + position.x + " Y: " + position.y);
});
这适用于所有浏览器。
编辑:
我从我正在使用的一个类中复制了代码,因此对 this.canvas 的 jQuery 调用是错误的。更新后的函数会找出导致事件的 DOM 元素 (targ),然后使用该元素的偏移量来找出正确的位置。
【讨论】:
GEE 是一个非常有用的库,用于解决画布问题,包括鼠标位置。
【讨论】:
我将分享迄今为止我创建的最防弹的鼠标代码。它适用于所有浏览器,包括各种填充、边距、边框和附加组件(如 stumbleupon 顶栏)
// Creates an object with x and y defined,
// set to the mouse position relative to the state's canvas
// If you wanna be super-correct this can be tricky,
// we have to worry about padding and borders
// takes an event and a reference to the canvas
function getMouse = function(e, canvas) {
var element = canvas, offsetX = 0, offsetY = 0, mx, my;
// Compute the total offset. It's possible to cache this if you want
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
// Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar)
// This part is not strictly necessary, it depends on your styling
offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
offsetY += stylePaddingTop + styleBorderTop + htmlTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
// We return a simple javascript object with x and y defined
return {x: mx, y: my};
}
您会注意到我使用了一些在函数中未定义的(可选)变量。它们是:
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
// They will mess up mouse coordinates and this fixes that
var html = document.body.parentNode;
htmlTop = html.offsetTop;
htmlLeft = html.offsetLeft;
我建议只计算一次,这就是为什么它们不在getMouse 函数中。
【讨论】:
我会使用 jQuery。
$(document).ready(function() {
$("#canvas_id").bind( "mousedown", function(e){ canvasClick(e); } );
}
function canvasClick( e ){
var x = e.offsetX;
var y = e.offsetY;
}
这样,您的画布可以位于页面上的任何位置,无论是相对的还是绝对的。
【讨论】:
接受的答案并非每次都有效。如果您不使用相对位置,则属性 offsetX 和 offsetY 可能会产生误导。
您应该使用来自 canvas API 的函数:canvas.getBoundingClientRect()。
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y);
}, false);
【讨论】:
JSFiddle 功能演示 http://jsfiddle.net/Dwqy7/5/
(注:不考虑边框,导致off-by-one):
向画布添加鼠标事件canvas.addEventListener("mousemove", mouseMoved);
调整event.clientX和event.clientY基于:canvas.offsetLeftwindow.pageXOffsetwindow.pageYOffsetcanvas.offsetTop
因此:
canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
最初的问题要求右上角的坐标(第二个功能)。 这些函数需要在它们可以访问画布元素的范围内。
0,0 在左上角:
function mouseMoved(event){
var canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}
0,0 在右上角:
function mouseMoved(event){
var canvasMouseX = canvas.width - (event.clientX - canvas.offsetLeft)- window.pageXOffset;
var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}
【讨论】: