document.elementFromPoint (x, y) не сообщает о правильных дочерних элементах - PullRequest
0 голосов
/ 28 февраля 2019

Согласно этому ответу , я должен быть в состоянии получить элемент, над которым произошел "сброс" элемента.Однако он сообщает о действительно странных и случайных результатах, которые всегда кажутся родительскими элементами, а не фактическим дочерним элементом, на который перетаскивается перетаскиваемый элемент.

Вот ПРИМЕР ПОЛНОГО КОДА на CodeSandbox ссоответствующие фрагменты, показанные ниже ...

<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);
}

1 Ответ

0 голосов
/ 01 марта 2019

Как указал @Joao, document.elementFromPoint() требует координат области просмотра, но VueDraggableResizable предоставляет координаты смещения (на основе настроенного соотношения сторон и границ блокировки) относительно исходного элемента drop.Вы все еще можете получить координаты области просмотра, выбрав их из самого перетаскиваемого элемента.

Шаги:

  1. Добавить ref - <vue-draggable-resizable> (который создаст массив ссылок на перетаскиваемый объект) и обновите обработчик dragstop, чтобы он также взял индекс, который мы будем использовать с соответствующим 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 отключите pointer-events на указанном перетаскиваемом элементе $el (соответствует индексу из предыдущего шага), такчто 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...