无法获取 div 元素的点击位置

can't get the click position of a div element

我想创建一个小地图。所以我在我的小地图中有 div 元素的准确表示。我希望用户使用小地图在站点中导航。

当我在我的迷你地图(灰色框)内单击时,我得到了正确的位置,但是当我单击“幻影”或绿色框时,我得到了不正确的尺寸,这导致了不正确的位置设置。

这里有一个展示:

function getClickPosition(e) {
  // I need the click position of the gray box 
  // but when I click on the green or red box I get their values
  console.log(e.layerX)
}
.minimap {
  height: 100px;
  width: 140px;
  background-color: #999;
  position: absolute;
  z-index: 100;
}
.viewport-layer {
 height: 20px;
 width: 35px;
 left: 20px;
 top: 15px;
 box-sizing: border-box;
 position: absolute;
 border: 2px solid green;
 z-index: 101;
 max-width: 100px;
}
.ghosty-box {
  position: absolute;
  top: 60px;
  left: 90px;
  height: 30px;
  width: 40px;
  background-color: red;
  z-index: 0; // should be in the background
}
<div class="minimap" onclick="getClickPosition(event)">
 <!-- user screen: green border -->
 <div class="viewport-layer">
 </div>
 <!-- dynamic size of the minimap -->
 <div class="relativeLayer">
  <!-- representation of the visible elements -->
  <div class="ghosty-box"></div>
 </div>
</div>

我的 e 控制台显示如下内容:

click { target: div.ghosty-box, ... layerX: 10, layerY: 11 }

click { target: div.viewportLayer, ... layerX: 33, layerY: 16 }

我原以为 z-index 会有所帮助。

对于获取 .minimap.relativeLayer 后面元素的点击位置,您有什么建议吗?

所以 target 总是 灰色框?

MDN 说(我在解释)layerX 是鼠标光标相对于被单击元素或其父元素之一的位置,该元素是绝对定位元素

你的ghosty-box是position: absolute,这意味着它被点击了,layerX是相对于它的。 如果你可以相对定位或者使用边距,就可以解决问题。

其他选项是使用 pageX 或 screenX 并自行计算偏移量,或者将叠加元素放置在小地图上并捕获对其的点击。

我不太确定你想从各个层次中得到什么读数,但有几点评论:

根据MDN

This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

如果您想要相对于灰色框的位置,如您的示例所示,您可能需要查看 event.pageX 或 event.clientX。正如这个片段:

function getClickPosition(e) {
  // I need the click position of the gray box 
  // but when I click on the green or red box I get their values
  console.log('pageX = ' + e.pageX);
  console.log('clientX = ' + e.clientX);
}
.minimap {
  height: 100px;
  width: 140px;
  background-color: #999;
  position: absolute;
  z-index: 100;
}
.viewport-layer {
 height: 20px;
 width: 35px;
 left: 20px;
 top: 15px;
 box-sizing: border-box;
 position: absolute;
 border: 2px solid green;
 z-index: 101;
 max-width: 100px;
}
.ghosty-box {
  position: absolute;
  top: 60px;
  left: 90px;
  height: 30px;
  width: 40px;
  background-color: red;
  z-index: 0; // should be in the background
}
<div class="minimap" onclick="getClickPosition(event)">
 <!-- user screen: green border -->
 <div class="viewport-layer">
 </div>
 <!-- dynamic size of the minimap -->
 <div class="relativeLayer">
  <!-- representation of the visible elements -->
  <div class="ghosty-box"></div>
 </div>
</div>

或者,当您处理点击事件时,当您有嵌套元素时,您可能想要检查点击了哪个实际元素 and/or 您可能想要也可能不想停止传播。例如,值得查看事件对象 console.log(e) 以查看目标是什么以及为获得正确目标而提供的其他设置。

我认为您需要 minimap 内单击元素的相对值。这将为您提供所单击项目的相对 X 和 Y - 以及相对 mouseX 和 mouseY(以及相对百分比位置)

function getClickPosition(e) {
  // I need the click position of the gray box 
  // but when I click on the green or red box I get their values
  if (e.target.classList.contains('minimap')) {
    console.log('clicked on minimap background');
    return;
  }
  let ref = e.target.closest('.minimap').getBoundingClientRect()
  let pos = e.target.getBoundingClientRect();
  let posY = pos.top - ref.top
  let posX = pos.left - ref.left
  let mouseY = e.clientY - ref.top
  let mouseYPerc = ((mouseY / ref.height) * 100).toFixed(2);
  let mouseX = e.clientX - ref.top
  let mouseXPerc = ((mouseX / ref.width) * 100).toFixed(2)
  console.log('my relative position X:' + posX + ' Y:' + posY);
  console.log("relative mouseX:" + mouseX + " (" + mouseXPerc + "%) horiz");
  console.log("relative mouseY:" + mouseY + " (" + mouseYPerc + "%) vert");
}
.minimap {
  height: 100px;
  width: 140px;
  background-color: #999;
  position: absolute;
  z-index: 100;
  margin: 50px;
  opacity: .2;
}

.viewport-layer {
  height: 20px;
  width: 35px;
  left: 20px;
  top: 15px;
  box-sizing: border-box;
  position: absolute;
  border: 2px solid green;
  z-index: 101;
  max-width: 100px;
}

.ghosty-box {
  position: absolute;
  top: 60px;
  left: 90px;
  height: 30px;
  width: 40px;
  background-color: red;
  z-index: 0; // should be in the background
}
<div class="minimap" onclick="getClickPosition(event)">
  <!-- user screen: green border -->
  <div class="viewport-layer">
  </div>
  <!-- dynamic size of the minimap -->
  <div class="relativeLayer">
    <!-- representation of the visible elements -->
    <div class="ghosty-box"></div>
  </div>
</div>

如果您真的不需要点击内部的元素,一个好的解决方案可能是放置一个覆盖整个小地图的绝对定位的空层来捕获点击。我用 class .position-layer

将它添加到您的代码段中

function getClickPosition(e) {
  // I need the click position of the gray box 
  // but when I click on the green or red box I get their values
  console.log(e.layerX);
  console.log(e.layerY);
}
.minimap {
  height: 100px;
  width: 140px;
  background-color: #999;
  position: absolute;
  z-index: 100;
}
.viewport-layer {
 height: 20px;
 width: 35px;
 left: 20px;
 top: 15px;
 box-sizing: border-box;
 position: absolute;
 border: 2px solid green;
 z-index: 101;
 max-width: 100px;
}
.ghosty-box {
  position: absolute;
  top: 60px;
  left: 90px;
  height: 30px;
  width: 40px;
  background-color: red;
  z-index: 0; // should be in the background
}

.position-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index:1000;
}
<div class="minimap">
 <!-- user screen: green border -->
 <div class="viewport-layer">
 </div>
 <!-- dynamic size of the minimap -->
 <div class="relativeLayer">
  <!-- representation of the visible elements -->
  <div class="ghosty-box"></div>
 </div>
 <div class="position-layer" onclick="getClickPosition(event)"></div>
</div>