我想做一个小绘画应用程序使用画布。所以我需要找到鼠标在画布上的位置。
当前回答
对于那些为移动设备和/或笔记本电脑/触摸屏显示器开发常规网站或PWAs(渐进式Web应用程序)的人来说,你可能已经登陆这里了,因为你可能已经习惯了鼠标事件,对触摸事件的痛苦体验还不熟悉……耶!
只有3条规则:
在鼠标移动或触摸移动事件期间尽可能少做。 在鼠标按下或触摸启动事件期间尽可能多地进行操作。 取消传播并防止触摸事件的默认值,以防止鼠标事件也在混合设备上触发。
不用说,触摸事件更复杂,因为可以有多个触摸事件,它们比鼠标事件更灵活(复杂)。这里我只讲一个触碰。是的,我很懒,但这是最常见的触摸方式。
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">
其他回答
基于@Patrick Boos的解决方案,但修复了中间滚动条的潜在问题。
export function getRelativeCoordinates(event: MouseEvent, referenceElement: HTMLElement) {
const position = {
x: event.pageX,
y: event.pageY,
};
const offset = {
left: referenceElement.offsetLeft,
top: referenceElement.offsetTop,
};
let reference = referenceElement.offsetParent as HTMLElement;
while (reference) {
offset.left += reference.offsetLeft;
offset.top += reference.offsetTop;
reference = reference.offsetParent as HTMLElement;
}
const scrolls = {
left: 0,
top: 0,
};
reference = event.target as HTMLElement;
while (reference) {
scrolls.left += reference.scrollLeft;
scrolls.top += reference.scrollTop;
reference = reference.parentElement as HTMLElement;
}
return {
x: position.x + scrolls.left - offset.left,
y: position.y + scrolls.top - offset.top,
};
}
你可以使用相对父类的getBoudingClientRect()。
document.addEventListener("mousemove", (e) => {
let xCoord = e.clientX - e.target.getBoundingClientRect().left + e.offsetX
let yCoord = e.clientY - e.target.getBoundingClientRect().top + e.offsetY
console.log("xCoord", xCoord, "yCoord", yCoord)
})
使用此方法快速获取鼠标位置:
Object.defineProperty(MouseEvent.prototype, "mouseX", {
get() {
return this.clientX - this.currentTarget.getBoundingClientRect().left;
}
});
Object.defineProperty(MouseEvent.prototype, "mouseY", {
get() {
return this.clientY - this.currentTarget.getBoundingClientRect().top;
}
});
例子:
document.body.onmousemove=function(e){console.log(e.mouseX,e.mouseY)}
因为我没有找到一个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>
完整的例子
原来的答案是把它放在一个iframe中。更好的解决方案是在填充设置为0px的画布上使用事件offsetX和offsetY。
<html>
<body>
<script>
var main=document.createElement('canvas');
main.width="200";
main.height="300";
main.style="padding:0px;margin:30px;border:thick dashed red";
document.body.appendChild(main);
// adding event listener
main.addEventListener('mousemove',function(e){
var ctx=e.target.getContext('2d');
var c=Math.floor(Math.random()*0xFFFFFF);
c=c.toString(16); for(;c.length<6;) c='0'+c;
ctx.strokeStyle='#'+c;
ctx.beginPath();
ctx.arc(e.offsetX,e.offsetY,3,0,2*Math.PI);
ctx.stroke();
e.target.title=e.offsetX+' '+e.offsetY;
});
// it worked! move mouse over window
</script>
</body>
</html>