查找相对于元素的鼠标位置

Posted

技术标签:

【中文标题】查找相对于元素的鼠标位置【英文标题】:Find mouse position relative to element 【发布时间】:2011-03-15 03:18:33 【问题描述】:

我想用画布制作一个小绘画应用程序。所以我需要找到鼠标在画布上的位置。

【问题讨论】:

完整解决方案:acko.net/blog/… 【参考方案1】:

由于我没有找到可以复制/粘贴的无 jQuery 答案,所以这是我使用的解决方案:

document.getElementById('clickme').onclick = function clickEvent(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>

JSFiddle of full example

【讨论】:

您需要round the bounding rect 以确保使用此方法的整数值。 新编辑应该修复滚动问题(使用 clientX/Y) 这个答案应该被投赞成票。谢谢anytimecoder 和@ErikKoopmans。 PSA:@mpen 的评论已过时;这种方法确实有效,即使在滚动的情况下也是如此。查看他们 Fiddle 的更新版本:jsfiddle.net/6wcsovp2 谢谢!注意:您需要e.currentTarget,而不是 e.target。否则,子元素会影响它【参考方案2】:

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

更新

@anytimecoder 在an answer 中有一个更新的纯 javascript 版本 -- 另请参阅 browser support for getBoundingClientRect()。

【讨论】:

它对你有用吗@ben,我会很感激“正确答案”或评论什么仍然不适合你。也许我可以提供更多帮助。 应该避免在事件处理程序中使用 $('selector') ,除非你想要非常缓慢的代码。预先选择您的元素,并在您的处理程序中使用预先选择的引用。 $(window) 也一样,执行一次并缓存它。 这个不用提了:如果是复制粘贴上面的代码,记得把var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();改成var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop(); 这怎么可能是答案,因为这个问题与 jQuery 无关? @Black 但有些人用 javascript 而不是 jquery 提问,因为 jquery 在他们的环境中可能不兼容。【参考方案3】:

下面计算鼠标与canvas元素的位置关系:

var example = document.getElementById('example'); 
example.onmousemove = function(e)  
    var x = e.pageX - this.offsetLeft; 
    var y = e.pageY - this.offsetTop; 

在此示例中,this 指的是example 元素,eonmousemove 事件。

【讨论】:

可能是我,但使用关键字“this”的两行代码缺少上下文? 绝对缺乏上下文。 'e' 是事件,'this' 是事件关联到的元素 var example = document.getElementById('example'); example.onmousemove = function(e) var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; 如果某些后代元素使用相对或绝对定位,这将不起作用。 您可以将this 切换为e.currentTarget,这将为您提供相对于您添加事件侦听器的元素的位置。 这似乎将位置相对于元素的 visible 部分,而不是整个元素。如果在视口中看不到部分元素并且有滚动条等,有没有办法适应这种情况?【参考方案4】:

当参考元素嵌套在其他可以使用绝对定位的元素中时,纯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元素偏移 非常适合滚动容器,只需稍作改动:将 while(reference !== undefined) 替换为 while(reference)。至少在 Chrome 中,offsetParent 最终不是undefined,而是null。只需检查 reference 是否真实,就可以确保它同时适用于 undefinednull 如果可以的话,我会再给一个 +1,因为让我知道有一个 offsetParent 属性,结果证明它在其他情况下也非常有用! 一般来说,检查 undefined 通常是个坏主意 我认为你需要减去scrollLeftscrollTop来补偿滚动的后代。【参考方案5】:

我尝试了所有这些解决方案,但由于我使用矩阵转换容器(panzoom 库)进行了特殊设置,但都没有奏效。这会返回正确的值,即使是缩放和平移:

mouseevent(e) 
 const x = e.offsetX,
       y = e.offsetY

但只有在没有子元素的情况下。这可以通过使用 CSS 使它们对事件“不可见”来规避:

.child 
   pointer-events: none;

【讨论】:

这绝对是 2019 年的做法。其他答案都装满了旧包袱。 @ColinD 谢谢!我忘了补充一点,这也适用于 IE11。 这对我有用。但是,我怀疑 1)很少有人支持 2)评分较高的答案更复杂 3)我没有看到任何缺点解释。有谁知道使用这种方法的任何弊端? @MarkE 没有任何可疑之处。这是 *** 的众多故障之一。您在顶部看到的那些答案是在此答案发布多年前发布的,因此他们获得了巨大的投票动力。一旦一个答案获得了这种势头,就很难而且很难击败它。 @MarkE 答案很简单:it's experimental。有些人可能在乎,有些人可能不在乎,但这是事实。【参考方案6】:

可以在此处找到有关此问题难度的详细说明:http://www.quirksmode.org/js/events_properties.html#position

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

【讨论】:

很遗憾,如果有任何类型的轮换,这将失败【参考方案7】:

我遇到了这个问题,但是为了使它适用于我的情况(在 DOM 元素上使用 dragover(在我的情况下不是画布)),我发现你只需要使用 offsetXoffsetY 在拖动鼠标事件上。

onDragOver(event)
 var x = event.offsetX;
 var y = event.offsetY;

【讨论】:

这对我很有用。为什么没有人对此表示赞同?我想知道是否有任何陷阱。如果我发现任何我会报告! event.offsetX 与鼠标指针当前所在的元素相关,而不是与附加了 dragover 侦听器的元素相关。如果您没有嵌套的元素结构,那么这很好,但如果您这样做,那么这将不起作用。【参考方案8】:

如果你想得到一个元素相关的layerX和layerY,也许你可以试试:

let bbox_rect = document.getElementById("dom-ID").getBoundingClientRect()
let layerX = e.clientX-bbox_rect.left
let layerY = e.clientY-bbox_rect.top

【讨论】:

【参考方案9】:

我 +1' Mark van Wyk 的回答让我朝着正确的方向前进,但并没有完全为我解决问题。在另一个元素中包含的元素中,我仍然有一个偏移量。

以下为我解决了:

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

换句话说 - 我只是堆叠了所有嵌套元素的所有偏移量

【讨论】:

+1 为您服务!这是我一直在寻找的答案。我有两个画布堆叠在一起,由于其他 div,坐标都是错误的。我知道这是问题所在,但不知道补偿它的逻辑/方程式。你也解决了我的问题! =D 谢谢!【参考方案10】:

对于那些为移动设备和/或带触摸屏的笔记本电脑/显示器开发常规网站或 PWA(渐进式 Web 应用程序)的人来说,您来到这里是因为您可能习惯于鼠标事件并且对有时会感到痛苦的事情不熟悉触摸事件的经验...耶!

只有 3 条规则:

    mousemovetouchmove 活动期间尽可能少做。 在mousedowntouchstart 活动期间尽可能多地做。 取消传播并阻止触摸事件的默认设置,以防止鼠标事件也在混合设备上触发。

不用说,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">

【讨论】:

【参考方案11】:

以上答案都不符合 IMO,所以我使用的是:

// 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

【讨论】:

【参考方案12】:

取自this tutorial,感谢置顶评论更正:

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 )
    ;

在画布上使用如下:

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

【讨论】:

【参考方案13】:
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 节点内向左偏移的像素数。

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

但是,对于可以从一行换行到下一行的内联级元素(例如span),offsetTopoffsetLeft 描述了第一个边框框的位置(使用Element.getClientRects() 来获取其宽度和高度),而offsetWidthoffsetHeight 描述边界框的尺寸(使用Element.getBoundingClientRect() 获取其位置)。因此,左侧、顶部、宽度和高度分别为offsetLeftoffsetTopoffsetWidthoffsetHeight 的框将不会成为带有换行文本的 span 的边界框。

HTMLElement.offsetTop

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

MouseEvent.pageX

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

MouseEvent.pageY

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

如需进一步说明,请参阅 Mozilla 开发者网络:

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

【讨论】:

虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。 我真的希望未来的读者有一个 JS API 可以为他们计算这个。 ;-) 这可能是最简单、完整、独立的答案。注释不言自明的代码只会分散注意力。 我同意@PatrickHund 的解释请求。我不是 CSS/JS 专家,了解更多关于 pageoffset 之间的关系对我很有帮助。感谢您考虑此请求! @cxw 好的,你现在是第二个反对票(有 1 个赞成票)...我现在添加了一个很长的解释,就像 4 行代码的 10 倍一样长。不客气,阅读愉快。我考虑了你的要求! :p @cxw 我搞砸了,添加了一个额外的绝对定位元素并强制画布元素本身离开屏幕,所以我不得不滚动到它,比如离开屏幕左/上 2000px。无法破解此代码。【参考方案14】:

const findMousePositionRelativeToElement = (e) => 
    const xClick = e.clientX - e.currentTarget.offsetLeft;
    const yClick = e.clientY - e.currentTarget.offsetTop;
    console.log(`x: $xClick`);
    console.log(`y: $yClick`);

    // or
    const rect = e.currentTarget.getBoundingClientRect();
    const xClick2 = e.clientX - rect.left;
    const yClick2 = e.clientY - rect.top;
    console.log(`x2: $xClick2`);
    console.log(`y2: $yClick2`);


【讨论】:

【参考方案15】:

我意识到我有点晚了,但这适用于 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 位置(相对于内容区域)。用 window.pageXOffset.找到视口的X位置

【讨论】:

感谢您成为唯一考虑滚动的回答者。考虑更改您的答案以添加 y 轴。【参考方案16】:

基于@Spider的解决方案,我的非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;

这适用于滚动和缩放(在这种情况下,有时它会返回浮动)。

【讨论】:

我会赞成,但这些不应该是页面偏移量的减号吗?是那个,还是第二部分的括号?【参考方案17】:

你可以得到它

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

【讨论】:

这将在 IE 中工作,还是 IE 仍然使用 window.event 而不是将事件传递给侦听器的第一个参数?编辑 - 我猜 IE 在版本 9 之前仍然缺少 canvas 元素,但由于 excanvas 之类的东西,这应该仍然支持 IE.... 这将给出相对于浏览器窗口的坐标,仍然需要使用 element.getBoundingClientRect() 确定它们是否在元素中 感谢您让我知道 getBoundingClientRect !!!!我从来没有意识到有这样的事情! @DavidW.Keith 的评论真的应该被认为是正确的答案!【参考方案18】:

通过 event.offsetX 和 event.offsetY 可以获得画布内的鼠标坐标。这里有一个小sn-p来证明我的观点:

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"  ></canvas>
    

【讨论】:

如果另一个 div 覆盖在画布上,它就不起作用,就像@opsb 说的那样【参考方案19】:

我实现了另一个我认为非常简单的解决方案,所以我想与大家分享。

所以,对我来说,问题是拖动的 div 会跳转到鼠标光标的 0,0。所以我需要捕捉鼠标在 div 上的位置来调整 div 的新位置。

我读取了 div PageX 和 PageY 并根据它设置顶部和左侧,然后获取值以调整坐标以将光标保持在 div 中的初始位置我使用 onDragStart 侦听器并存储e.nativeEvent.layerXe.nativeEvent.layerY 仅在初始触发器中为您提供鼠标在可拖动 div 内的位置。

示例代码:

 onDrag=(e) => 
          let newCoords;
          newCoords =  x: e.pageX - this.state.correctionX, y: e.pageY - this.state.correctionY ;
          this.props.onDrag(newCoords, e, item.id);
        
        onDragStart=
          (e) => 
            this.setState(
              correctionX: e.nativeEvent.layerX,
              correctionY: e.nativeEvent.layerY,
            );
          

我希望这会帮助遇到我遇到的同样问题的人:)

【讨论】:

【参考方案20】:
function myFunction(e) 
    var x =  e.clientX - e.currentTarget.offsetLeft ; 
    var y = e.clientY - e.currentTarget.offsetTop ;

这工作正常!

【讨论】:

【参考方案21】:

您可以使用relative 父级的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)
)

【讨论】:

【参考方案22】:

您可以简单地使用 jQuery 的 event.pageX 和 event.pageY 和 jQuery 的方法 offset() 来获取鼠标相对于元素的位置。

  $(document).ready(function() 
    $("#myDiv").mousemove(function(event)            
      var X = event.pageX - $(this).offset().left;
      var Y = event.pageY - $(this).offset().top;
      $(".cordn").text("(" + X + "," + Y + ")");
    );
  );

您可以在此处查看示例:How to find mouse position relative to element

【讨论】:

不是每个人都使用 jQuery。【参考方案23】:

您必须了解页面的结构,因为如果您的画布是一个 div 的子级,而后者又是另一个 div 的子级......那么故事会变得更加复杂。这是我在 div 的 2 个级别内的画布的代码:

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);

);

【讨论】:

【参考方案24】:

原来的答案是把它放在一个 iframe 中。更好的解决方案是在填充设置为 0px 的画布上使用事件 offsetX 和 offsetY。

<html>
<body>
<script>

var main=document.createElement('canvas');
main.;
main.;
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>

【讨论】:

【参考方案25】:

基于@Patrick Boos solution,但修复了中间滚动条的潜在问题。

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,
  ;

【讨论】:

【参考方案26】:

我必须在带有滚动条的非常宽的 div 内获取光标位置。目标是将元素拖到 div 的任意位置。

在滚动的深处获得鼠标位置。

$('.canvas').on('mousemove', function(e)
    $(dragElement).parent().css('top', e.currentTarget.scrollTop + e.originalEvent.clientY );
    $(dragElement).parent().css('left', e.currentTarget.scrollLeft + e.originalEvent.clientX )
);

【讨论】:

【参考方案27】:

这是我得到的。

    $(".some-class").click(function(e) 

    var posx = 0;
    var posy = 0;

    posx = e.pageX;
    posy = e.pageY;

    alert(posx);
    alert(posy);
);

【讨论】:

以上是关于查找相对于元素的鼠标位置的主要内容,如果未能解决你的问题,请参考以下文章

如何确定鼠标相对于父元素的悬停位置

鼠标/手指相对于元素的坐标(px转百分比)

jQuery怎么获取鼠标的位置坐标

鼠标相对于屏幕的位置鼠标相对于窗口的位置和获取鼠标相对于文档的位置

Javascript中的DOM实现显示鼠标的空间位置

canvas 使用 isPointInPath() 判断鼠标位置是否在绘制的元素上