获取相对于最接近的相对父级的点击位置

时间:2019-02-08 01:21:45

标签: javascript html css

我想在用户点击的位置在较大的div内渲染一个较小的div。我可以通过从offsetX获取offsetYevent来做到这一点。这很好,直到较大的div内有子div。 onclick事件监听器会触发最外部的div,但是event属性是相对于单击的子项而不是父项而言的。

我在这里做了一个小例子

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

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

父母必须留一个Flexbox,如果可以的话,我想避免在每个孩子身上放置听众作为解决方法。

谢谢!

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>

1 个答案:

答案 0 :(得分:1)

是的,没有必要向孩子添加单个事件侦听器。您可以使用dive.target.offsetLeft来获得子e.target.offsetTop的相对偏移,然后将其添加到e.offsetXe.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