【问题标题】:document.elementFromPoint(x, y) isn't reporting correct child elementsdocument.elementFromPoint(x, y) 没有报告正确的子元素
【发布时间】:2019-02-28 15:14:49
【问题描述】:

According to this answer,我应该能够得到一个元素“drop”发生的元素。但是,它报告的结果非常奇怪和随机,这些结果似乎总是父元素,而不是拖放元素所在的实际子元素。

Here's the FULL CODE EXAMPLE on CodeSandbox 与下面显示的相关 sn-ps...

<div>
    <div id="sidebar">
      <drag :transfer-data="{ type: 'textbox', width: 330, height: 50 }" class="draggable-item"
        >Textbox
        <div slot="image" class="drag-image"><div class="field-container" style="width: 330px;height: 50px;">Texbox</div></div></drag
      >
    </div>
    <div id="pages-container" @click.self="deselectAll();">
      <b-alert show variant="info" class="text-center">Drag controls from the left sidebar to the pages below.</b-alert>
      <drop
        class="page-container"
        v-for="(p, index) in pages"
        @drop="onDrop"
        @click.self="deselectAll();"
        :data-page-number="p.pageNumber"
        :key="p.pageNumber + '_page_' + index"
        :style="{ width: p.width + 'px', height: p.height + 'px' }"
      >
        <img src="https://www.kirupa.com/flash/images/single_column_text.png" width="100%" height="100%" :data-page-number="p.pageNumber" @click.self="deselectAll();" />
        <div style="position: absolute;top:0;bottom:0;left:0;right:0;background-color:white;opacity:0" :data-page-number="p.pageNumber" @click.self="deselectAll();"></div>

        <vue-draggable-resizable
          :id="f.id"
          :style="{ 'z-index': '1044 !important' }"
          :class="{ 'field-container grabbable': true, selected: f.isSelected }"
          v-for="(f, f_index) in getPageFields(fields, p.pageNumber)"
          :key="f.id"
          :min-width="20"
          :min-height="20"
          :x="f.left"
          :y="f.top"
          :w="f.width"
          :h="f.height"
          :parent="false"
          :z-index="f.isSelected ? '1045 !important' : '1044 !important'"
          :prevent-deactivation="true"
          :active.sync="f.isSelected"
          @resizestop="onResizeStop"
          @dragstop="onDragStop"
          @activated="onActivated(f.id);"
          @clicked="onActivated(f.id);"
          >id: {{ f.id }} <br />
          page: {{ p.pageNumber }} fieldIndex: {{ f_index }} selected: {{ f.isSelected }}</vue-draggable-resizable
        >
      </drop>
    </div>
</div>

此处显示了相关的 JavaScript(页码警报测试始终为undefined)...

onDragStop(x, y) {
  //...
  const el = document.elementFromPoint(x, y);
  alert("Dropped onto page number: " + el.dataset.pageNumber);
}

【问题讨论】:

  • 问题在于DocumentOrShadowRoot.elementFromPoint() 采用viewport 坐标,而onDragStop() 上可用的坐标是相对于您要放置对象的区域的开始到。尽管我尝试了一段时间,但我以前没有使用 Vue 的经验,因此找不到解决方案,但本质上,如果您打算使用 elementFromPoint() 方法,您将需要一种查找视口坐标的方法。

标签: javascript vue.js vuejs2 drag-and-drop


【解决方案1】:

正如@Joao 指出的那样,document.elementFromPoint() 需要视口坐标,但VueDraggableResizable 提供相对于初始放置元素的偏移坐标(基于其配置的锁定纵横比和边界)。您仍然可以通过从可拖动项目本身抓取它们来获取视口坐标。

步骤:

  1. ref 添加到&lt;vue-draggable-resizable&gt;(这将创建一个对可拖动对象的引用数组),并更新dragstop-handler 以获取我们将与适用的ref 一起使用的索引下一步:

    // template
    <vue-draggable-resizable
        v-for="(f, f_index) in ..."
        ref="draggable" ?
        @dragstop="(x,y) => onDragStop(x,y,f_index)" ?
        >
    
    // script
    onDragStop(x, y, ?index) { ... }
    
  2. dragstop 处理程序中,禁用引用的可拖动对象$el 上的pointer-events(对应于上一步中的索引),以便document.elementFromPoint() 可以抓取可拖动对象视口坐标下方的元素,我们将其我会得到getBoundingClientRect()

    onDragStop(x, y, index) {
      const draggable = this.$refs.draggable[index].$el;
      draggable.style.pointerEvents = 'none'?
    
      const { left: dragX, top: dragY } = draggable.getBoundingClientRect();
      const targetElem = document.elementFromPoint(dragX, dragY);
    
      draggable.style.pointerEvents = 'auto'
    
      ...
    }
    

demo

【讨论】:

  • 我必须parseInt pageNumber 才能分配它,这样该字段才不会消失。 codesandbox.io/s/r5r7q54jrn 但它运行良好。我现在只需要弄清楚如何在新页面上找到正确的位置,我会很好的。您认为首先使用数学减去页面高度会更容易,还是应该只是新容器页面的偏移量?谢谢!
  • 我把它放在另一页的地方。我必须弄清楚它在第二页上的位置,以便我可以将它移动到第二页并更新该页面上的相对坐标。
  • 仅供参考,我已经用更简单的确定视口坐标的解决方案更新了答案。关于另一页上的放置坐标:我认为不应该考虑高度(这需要考虑边框/边距/填充等)。相反,我会从可拖动的坐标中减去目标元素的坐标。请参阅更新后的演示,其中包含 console.log 用于 offsetXoffsetY
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多