問題

私は、ユーザーがクリックする時点で大きなdivの中に小さなdivをレンダリングしたいと思います。私はoffsetXoffsetYeventから取得することでこれを行うことができます。これは、大きなdivの中に子divがあるまでうまく動作します。 outermost divのonclickイベントリスナーは起動しますが、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> 

  ベストアンサー

ええ、個々のイベントリスナーを子に追加する必要はありません。 e.target.offsetLefte.target.offsetTopの子divの相対オフセットを取得し、それをe.offsetXe.offsetYに追加すると、divsの数に関係なくcmの正しい場所が与えられます。

 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'  
}
 

layerXlayerYを指摘するための@Alok Singhへのクレジット

  同じタグがついた質問を見る

javascripthtmlcss