【问题标题】:can't get the click position of a div element无法获取 div 元素的点击位置
【发布时间】:2021-06-06 17:04:32
【问题描述】:

我想创建一个小地图。所以我在我的小地图中准确地表示了 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总是是灰色框?

【问题讨论】:

  • 我过去遇到的事情是由于元素的嵌套性质,即使您想要点击的是 div,您实际上可能正在点击 P 标签或 A 标签。最好的方法是使用一个看起来不像按钮的按钮,或者只使用一个常规按钮。这有利于用户体验,因为它向他们展示了点击的位置,并且使您的代码更容易,因为您只需聆听按钮按下。
  • 那么,无论在小地图内点击什么元素,你想得到那个元素相对于小地图边界的位置? e.target 是否总是必须是小地图?
  • @Kwright02 无需引入不需要的按钮即可处理目标问题的多种其他方法
  • @Kinglish,我只是想要相对位置。价值来自哪里并不重要。我认为通过具有页面尺寸的 div 可以更轻松地工作。
  • @wittgenstein - 看看我更新的答案是否有帮助。

标签: javascript html css dom-events z-index


【解决方案1】:

我认为您想要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>

【讨论】:

  • 这正是我想要实现的。谢谢!
【解决方案2】:

我不确定你想要从各个层中得到什么读数,但有几个 cmets:

根据MDN:

此功能是非标准的,不在标准轨道上。不要在面向 Web 的生产站点上使用它:它不适用于每个用户。实现之间也可能存在很大的不兼容性,并且行为可能会在未来发生变化。

如果您想要相对于灰色框的位置,如您的示例所示,您可能需要查看 event.pageX 或 event.clientX。就像在这个 sn-p 中一样:

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>

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

【讨论】:

  • 这看起来很不错。我稍后会回复你。现在谢谢。
【解决方案3】:

如果您真的不需要点击其中的元素,一个好的解决方案可能是放置一个绝对定位的空图层,覆盖整个小地图以捕获点击。我用.position-layer类将它添加到你的sn-p

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>

【讨论】:

  • 不错。我也想这样做,但想不通。得到了你的支持。
【解决方案4】:

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

你的幽灵盒子是position: absolute,这意味着它被点击了,layerX是相对于它的。 如果您可以相对定位或使用边距,那将解决问题。

其他选项是使用 pageX 或 screenX 并自己计算偏移量,或者将覆盖元素放置在小地图上并捕捉点击。

【讨论】:

  • 即使我将元素设置为position: relative,它们仍然被锁定为目标。我认为您对 pageX 或 screenX 的建议将导致目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 1970-01-01
  • 1970-01-01
  • 2019-09-17
相关资源
最近更新 更多