首页 > 解决方案 > 获取相对于最近的相对父级的点击位置

问题描述

我想在用户点击的地方在一个较大的 div 中渲染一个小 div。我可以通过offsetXoffsetY. event这工作正常,直到较大的 div 中有子 div。onclick最外层 div 的事件侦听器触发,但event属性随后相对于单击的子级而不是父级。

我在这里做了一个小例子

https://codepen.io/markgeeromano311/pen/rPppRV

您可以在单击左子项时看到它工作正常,因为它的 x 和 y 与父项位于同一点。但是,当您单击正确的孩子时,它显然会中断。

父母必须保持弹性盒,如果可以的话,我想避免将听众放在每个孩子身上作为修复。

谢谢!

document.getElementById('outer').addEventListener('click', renderCM)

function renderCM(e) {
  const cm = document.getElementById('contextmenu')
  console.log(e)
  cm.style.left = e.offsetX + 'px'
  cm.style.top = e.offsetY + 'px'
  cm.style.display = 'block'
}
#outer {
  width: 200px;
  height: 200px;
  background-color: red;
  display: flex;
  position: relative;
  padding: 5px;
}

.inner {
  width: 50%;
  height: 100%;
  background-color: blue;
  border: 1px solid;
}

#contextmenu {
  display: none;
  width: 10px;
  height: 10px;
  position: absolute;
  background-color: yellow;
}

#outermost {
  height: 350px;
  background-color: orange;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
<div id="outermost">
  <div id="outer">
    <div id="contextmenu"></div>
    <div onclick=alert class="inner">
    </div>
    <div class="inner">
    </div>
  </div>

标签: javascripthtmlcss

解决方案


是的,没有必要为孩子添加单独的事件监听器。您可以div使用e.target.offsetLeftand获得子项的相对偏移量e.target.offsetTop,然后将其添加到e.offsetXande.offsetY它应该为您提供正确的位置,而cm不管 的数量是多少divs

document.getElementById('outer').addEventListener('click', renderCM)

function renderCM(e) {
	const cm = document.getElementById('contextmenu')
	cm.style.left = e.target.offsetLeft + e.offsetX + 'px'
	cm.style.top = e.target.offsetTop + e.offsetY + 'px'
	cm.style.display = 'block'	
}
#outer {
  width: 200px;
  height:200px;
  background-color: red;
  display: flex;
  position: relative;
  padding: 5px;
}

.inner {
  width: 50%;
  height: 100%;
  background-color: blue;
  border: 1px solid;
}

#contextmenu {
  display: none;
  width: 10px;
  height: 10px;
  position: absolute;
  background-color: yellow;
}

#outermost {
  width: 350px;
  height: 350px;
  background-color: orange;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
<div id="outer">
  <div id="contextmenu"></div>
  <div class="inner"></div>
  <div class="inner"></div>
  <div class="inner"></div>
  <div class="inner"></div>
  <div class="inner"></div>
  <div class="inner"></div>
</div>

编辑:更好的解决方案:

function renderCM(e) {
    const cm = document.getElementById('contextmenu')
    cm.style.left = e.layerX + 'px'
    cm.style.top = e.layerY + 'px'
    cm.style.display = 'block'  
}

感谢@Alok Singh 指出layerXlayerY


推荐阅读