javascript - document.elementFromPoint(x, y) 没有报告正确的子元素
问题描述
根据这个答案,我应该能够得到元素“drop”发生的元素。然而,它报告了非常奇怪和随机的结果,这些结果似乎总是父元素,而不是拖放元素所在的实际子元素。
这是 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);
}
解决方案
正如@Joao 指出的那样,document.elementFromPoint()
需要视口坐标,但VueDraggableResizable
提供相对于初始放置元素的偏移坐标(基于其配置的锁定纵横比和边界)。您仍然可以通过从可拖动项目本身获取视口坐标来获取它们。
脚步:
添加一个
ref
to<vue-draggable-resizable>
(这将创建一个对可拖动对象的引用数组),并更新-handler 以获取我们将在下一步中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) { ... }
在
dragstop
-handler 中,禁用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' ... }
推荐阅读
- android - 将最小、目标和编译 SDK 设置为相同版本会更好吗?
- php - PHPMailer:被 Strato 托管阻止?
- cucumber - Cucumber 框架迁移 - 现有的放心到空手道框架
- tensorflow - 收到错误“未创建保护程序,因为图中没有要恢复的变量”
- php - 图像垂直显示而不是水平显示
- mysql - 如何使用 MySQL 全文搜索土耳其语字符?
- php - 多个实体的 ApiPlatform PUT 关系(注释)
- wpf - 未评估嵌套 XAML WPF 中的绑定
- macports - 如何在错误情况下中止 macports 端口文件?
- django - 如何在 Next.js 中利用 Django 的身份验证系统?