find相对于元素的鼠标位置

我想用canvas做一个小的绘画应用程序。 所以我需要find鼠标在canvas上的位置。

对于使用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

这将计算鼠标与canvas元素的位置关系:

 var X = e.pageX - this.offsetLeft var Y = e.pageY - this.offsetTop 

这与Chrome,Safari,Firefox和Opera一起工作。 IE 9给出了一个消息,它不支持canvas

这个问题的难度可以在这里find: http : //www.quirksmode.org/js/events_properties.html#position

使用在那里描述的技术,您可以在文档中find鼠标的位置。 然后你只要检查它是否在元素的边界框内,通过调用element.getBoundingClientRect()就可以find它,它将返回一个具有以下属性的对象:{bottom,height,left,right,top,width }。 从那里,找出是否发生在你的元素内部是微不足道的。

我在2010年发现了这个问题,但似乎没有人满意:在纯JavaScript中没有答案,当参考元素嵌套在其他人可以与绝对定位时,返回相对坐标。 这是我的解决scheme:

 var container = myReferenceElement; function getRelativeCoordinates ( e ) { var pos = {}, offset = {}, ref; ref = container.offsetParent; pos.x = !! e.touches ? e.touches[ 0 ].pageX : e.pageX; pos.y = !! e.touches ? e.touches[ 0 ].pageY : e.pageY; offset.left = container.offsetLeft; offset.top = container.offsetTop; while ( ref ) { offset.left += ref.offsetLeft; offset.top += ref.offsetTop; ref = ref.offsetParent; } return { x : pos.x - offset.left, y : pos.y - offset.top, }; } 

因为我没有findjQuery的免费答案,我可以复制/粘贴这里是我使用的解决scheme:

 //e = mouse click event var rect = e.target.getBoundingClientRect(); var x = e.pageX - rect.left; //x position within the element var y = e.pageY - rect.top; //y position within the element 

JSFiddle的完整例子

我+1马克·范·威克的答案,因为它让我在正确的方向,但没有完全解决我的问题。 在另一个元素中包含的元素中,我仍然有一个偏移。

FOllowing为我解决了这个问题:

  x = e.pageX - this.offsetLeft - $(elem).offset().left; y = e.pageY - this.offsetTop - $(elem).offset().top; 

换句话说 – 我只是将所有嵌套元素的所有偏移量叠加起来

以上的答案都不是令人满意的国际海事组织,所以这就是我使用的:

 // Cross-browser AddEventListener function ael(e, n, h){ if( e.addEventListener ){ e.addEventListener(n, h, true); }else{ e.attachEvent('on'+n, h); } } var touch = 'ontouchstart' in document.documentElement; // true if touch device var mx, my; // always has current mouse position IN WINDOW if(touch){ ael(document, 'touchmove', function(e){var ori=e;mx=ori.changedTouches[0].pageX;my=ori.changedTouches[0].pageY} ); }else{ ael(document, 'mousemove', function(e){mx=e.clientX;my=e.clientY} ); } // local mouse X,Y position in element function showLocalPos(e){ document.title = (mx - e.getBoundingClientRect().left) + 'x' + Math.round(my - e.getBoundingClientRect().top); } 

如果您需要知道页面的当前Y滚动位置:

 var yscroll = window.pageYOffset || (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop; // scroll Y position in page 

从本教程中获取更正,并感谢顶级评论:

 function getMousePos( canvas, evt ) { var rect = canvas.getBoundingClientRect(); return { x: Math.floor( ( evt.clientX - rect.left ) / ( rect.right - rect.left ) * canvas.width ), y: Math.floor( ( evt.clientY - rect.top ) / ( rect.bottom - rect.top ) * canvas.height ) }; } 

在canvas上使用如下:

 var canvas = document.getElementById( 'myCanvas' ); canvas.addEventListener( 'mousemove', function( evt ) { var mousePos = getMousePos( canvas, evt ); } ); 

我意识到我有点晚了,但是这与PURE JavaScript一起工作,如果元素大于视口并且用户已经滚动,它甚至会给出元素内指针的坐标。

 var element_offset_x ; // The distance from the left side of the element to the left of the content area ....// some code here (function declaration or element lookup ) element_offset_x = element.getBoundingClientRect().left - document.getElementsByTagName("html")[0].getBoundingClientRect().left ; ....// code here function mouseMoveEvent(event) { var pointer_location = (event.clientX + window.pageXOffset) - element_offset_x ; } 

怎么运行的。

我们要做的第一件事是获取相对于当前视口的HTML元素(内容区域)的位置。 如果页面有滚动条并被滚动,那么由getBoundingClientRect().left返回的html标签的数字将是负数。 然后我们使用这个数字来计算元素和内容区域左边的距离。 用element_offset_x = element.getBoundingClientRect().left......;

知道元素与内容区域的距离。 event.clientX给我们从视口指针的距离。 理解视口和内容区域是两个不同的实体是很重要的,如果页面滚动,视口可以移动。 因此,即使页面被滚动,clientX也会返回相同的数字。

为了弥补这一点,我们需要将指针的x位置(相对于视口)添加到视口的x位置(相对于内容区域)。 视窗的X位置可以通过window.pageXOffset.findwindow.pageXOffset.

 canvas.onmousedown = function(e) { pos_left = e.pageX - e.currentTarget.offsetLeft; pos_top = e.pageY - e.currentTarget.offsetTop; console.log(pos_left, pos_top) } 

HTMLElement.offsetLeft

HTMLElement.offsetLeft只读属性返回HTMLElement.offsetParent节点中当前元素的左上angular向左偏移的像素数。

对于块级元素, offsetTopoffsetLeftoffsetWidthoffsetHeight描述元素相对于offsetParent的边框。

但是,对于可以从一行换行到下一行的内联级元素(例如span ), offsetTopoffsetLeft描述第一个边框的位置(使用Element.getClientRects()来获取其宽度和高度),而offsetWidthoffsetHeight描述边界框的尺寸(使用Element.getBoundingClientRect()来获得它的位置)。 因此, offsetLeftoffsetTopoffsetWidthoffsetHeight左边,顶部,宽度和高度的offsetLeft不会是包含文本的跨度的边界框。

HTMLElement.offsetTop

HTMLElement.offsetTop只读属性返回当前元素相对于offsetParent节点顶部的距离。

MouseEvent.pageX

pageX只读属性返回相对于整个文档的事件像素的X(水平)坐标。 该属性考虑到页面的任何水平滚动。

MouseEvent.pageY

MouseEvent.pageY只读属性返回相对于整个文档的事件像素的Y(垂直)坐标。 该属性考虑了页面的任何垂直滚动。

有关详细解释,请参阅Mozilla开发者networking:

https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY https:// developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop

基于@ Spider的解决scheme,我的非JQuery版本是这样的:

 // Get the container element's bounding box var sides = document.getElementById("container").getBoundingClientRect(); // Apply the mouse event listener document.getElementById("canvas").onmousemove = (e) => { // Here 'self' is simply the current window's context var x = (e.clientX - sides.left) + self.pageXOffset; var y = (e.clientY - sides.top) + self.pageYOffset; } 

这与滚动和缩放(在这种情况下有时它返回浮动)。

你可以得到它

 var element = document.getElementById(canvasId); element.onmousemove = function(e) { var xCoor = e.clientX; var yCoor = e.clientY; } 

你必须知道你的页面的结构,因为如果你的canvas是一个div的孩子,而div又是另一个div的孩子,那么故事变得更加复杂。 这里是我的代码在一个canvas里面的两个级别的div:

 canvas.addEventListener("click", function(event) { var x = event.pageX - (this.offsetLeft + this.parentElement.offsetLeft); var y = event.pageY - (this.offsetTop + this.parentElement.offsetTop); console.log("relative x=" + x, "relative y" + y); 

});

原来的答案说,把它放在一个iframe。 更好的解决scheme是在填充设置为0px的canvas上使用事件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> 

由于event.offsetX和event.offsetY,可以获得canvas内的鼠标坐标。 这是一个小小的片段来certificate我的观点:

 c=document.getElementById("c"); ctx=c.getContext("2d"); ctx.fillStyle="black"; ctx.fillRect(0,0,100,100); c.addEventListener("mousemove",function(mouseEvt){ // the mouse's coordinates on the canvas are just below x=mouseEvt.offsetX; y=mouseEvt.offsetY; // the following lines draw a red square around the mouse to prove it ctx.fillStyle="black"; ctx.fillRect(0,0,100,100); ctx.fillStyle="red"; ctx.fillRect(x-5,y-5,10,10); }); 
 body { background-color: blue; } canvas { position: absolute; top: 50px; left: 100px; } 
 <canvas id="c" width="100" height="100"></canvas>