我想使用画布(canvas)制作一个小的绘画应用程序。因此,我需要在画布上找到鼠标的位置。
我想使用画布(canvas)制作一个小的绘画应用程序。因此,我需要在画布上找到鼠标的位置。
因为我找不到一个没有 jQuery 的答案可以复制/粘贴,所以这是我使用的解决方案:
document.getElementById('clickme').onclick = function(e) {
// e = Mouse click event.
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left; //x position within the element.
var y = e.clientY - rect.top; //y position within the element.
console.log("Left? : " + x + " ; Top? : " + y + ".");
}
#clickme {
margin-top: 20px;
margin-left: 100px;
border: 1px solid black;
cursor: pointer;
}
<div id="clickme">Click Me -<br>
(this box has margin-left: 100px; margin-top: 20px;)</div>
e.currentTarget
而不是 e.target
。否则,子元素会影响它。 - Maxim Georgievskiy对于使用JQuery的人:
有时候,当你有嵌套元素,并且其中一个元素具有事件附加到它时,了解你的浏览器将哪个元素视为父级可能会很困惑。在这种情况下,你可以指定父级元素。
你可以获取鼠标位置,然后从父元素的偏移位置中减去它。
var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;
如果您尝试获取滚动窗格内页面上的鼠标位置:
var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();
或相对于页面的位置:
var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
请注意以下性能优化:
var offset = $('#element').offset();
// Then refer to
var x = evt.pageX - offset.left;
这种方式,JQuery无需为每行代码查找#element
。
有一种新的、仅基于JavaScript的版本在@anytimecoder的答案中,另请参见getBoundingClientRect()的浏览器支持情况。
var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();
更正为 var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
。 - Raj Nathaniconst example = document.getElementById('example');
example.onmousemove = function(e) {
const x = e.pageX - e.currentTarget.offsetLeft;
const y = e.pageY - e.currentTarget.offsetTop;
}
var example = document.getElementById('example');
example.onmousemove = function(e) {
var X = e.pageX - this.offsetLeft;
var Y = e.pageY - this.offsetTop;
}
- Nick Bisby在纯JavaScript中,当参考元素嵌套在其他具有绝对定位的元素中时,没有返回相对坐标的答案。以下是解决此情况的方法:
function getRelativeCoordinates (event, referenceElement) {
const position = {
x: event.pageX,
y: event.pageY
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop
};
let reference = referenceElement.offsetParent;
while(reference){
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent;
}
return {
x: position.x - offset.left,
y: position.y - offset.top,
};
}
html
元素的偏移量。 - apieceofbartscrollLeft
和 scrollTop
来补偿已滚动的后代元素。 - Robertoffset.left += reference.offsetLeft - reference.scrollLeft + parseInt(getComputedStyle(reference).paddingLeft);
,同样适用于顶部。 - Andrew我尝试了所有这些解决方案,但由于我的特殊设置与矩阵变换容器(panzoom库)不兼容,所以没有一个可行。即使是缩放和平移,这个解决方案也可以返回正确的值:
mouseevent(e) {
const x = e.offsetX,
y = e.offsetY
}
但仅在没有子元素阻碍的情况下才能这样做。可以通过使用CSS将它们对事件“隐藏”来规避此问题:
.child {
pointer-events: none;
}
element.getBoundingClientRect()
来找到元素的边界框,它将返回一个具有以下属性的对象:{ bottom, height, left, right, top, width }
。从那里开始,很容易确定事件是否发生在您的元素内部。我遇到了这个问题,但为了使它适用于我的情况(在DOM元素上使用dragover(在我的情况下不是canvas)),我发现你只需要在dragover-mouse事件中使用offsetX
和offsetY
。
onDragOver(event){
var x = event.offsetX;
var y = event.offsetY;
}
如果您想获取与一个元素相关的layerX和layerY,也许可以尝试:
let bbox_rect = document.getElementById("dom-ID").getBoundingClientRect()
let layerX = e.clientX-bbox_rect.left
let layerY = e.clientY-bbox_rect.top
我将Mark van Wyk的答案评为有帮助,因为它让我朝正确的方向前进,但是对于我来说并没有完全解决问题。我仍然需要在包含另一个元素的元素中绘制元素时进行偏移。
以下内容对我有帮助:
x = e.pageX - this.offsetLeft - $(elem).offset().left;
y = e.pageY - this.offsetTop - $(elem).offset().top;
如果您正在为移动设备和/或带有触摸屏的笔记本电脑/监视器开发常规网站或PWA(渐进式Web应用程序),那么您来到这里可能是因为您习惯于鼠标事件,但对触摸事件的体验可能会有些痛苦…太好了!
只有三条规则:
mousemove
或touchmove
事件中尽量少做。mousedown
或touchstart
事件中尽可能多地完成操作。不用说,由于touch
事件可能存在多个且比鼠标事件更加灵活(复杂),因此事情变得更加复杂。我只会在这里介绍单点触控。是的,我有点懒,但它是最常见的触摸类型。
var posTop;
var posLeft;
function handleMouseDown(evt) {
var e = evt || window.event; // Because Firefox, etc.
posTop = e.target.offsetTop;
posLeft = e.target.offsetLeft;
e.target.style.background = "red";
// The statement above would be better handled by CSS
// but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
var e = evt || window.event;
var x = e.offsetX; // Wonderfully
var y = e.offsetY; // Simple!
e.target.innerHTML = "Mouse: " + x + ", " + y;
if (posTop)
e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
var e = evt || window.event;
e.target.innerHTML = "";
}
function handleMouseUp(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
var e = evt || window.event;
var rect = e.target.getBoundingClientRect();
posTop = rect.top;
posLeft = rect.left;
e.target.style.background = "green";
e.preventDefault(); // Unnecessary if using Vue.js
e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
var e = evt || window.event;
var pageX = e.touches[0].clientX; // Touches are page-relative
var pageY = e.touches[0].clientY; // not target-relative
var x = pageX - posLeft;
var y = pageY - posTop;
e.target.innerHTML = "Touch: " + x + ", " + y;
e.target.innerHTML += "<br>" + pageX + ", " + pageY;
e.preventDefault();
e.stopPropagation();
}
function handleTouchEnd(evt) {
var e = evt || window.event;
e.target.style.background = "yellow";
// Yes, I'm being lazy and doing the same as mouseout here
// but obviously you could do something different if needed.
e.preventDefault();
e.stopPropagation();
}
div {
background: yellow;
height: 100px;
left: 50px;
position: absolute;
top: 80px;
user-select: none; /* Disable text selection */
-ms-user-select: none;
width: 100px;
}
<div
onmousedown="handleMouseDown()"
onmousemove="handleMouseMove()"
onmouseout="handleMouseOut()"
onmouseup="handleMouseUp()"
ontouchstart="handleTouchStart()"
ontouchmove="handleTouchMove()"
ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.
喜欢使用Vue.js吗?我也是!那么你的HTML代码应该是这样的:
<div @mousedown="handleMouseDown"
@mousemove="handleMouseMove"
@mouseup="handleMouseUp"
@touchstart.stop.prevent="handleTouchStart"
@touchmove.stop.prevent="handleTouchMove"
@touchend.stop.prevent="handleTouchEnd">