如何将拖拽的HTML元素放置在鼠标释放的对应坐标位置
解决方案
要实现拖拽元素精准定位到鼠标松开位置,需要调整样式定位规则与拖拽事件的坐标计算逻辑,具体修改如下:
关键调整点
- 定位规则修改
- 放置目标容器
.form添加position: relative,作为内部拖拽元素绝对定位的参考基准 - 可拖拽元素
.control添加position: absolute,支持自定义坐标放置 - 补充缺失的
.hide类样式,实现拖拽过程中源元素隐藏的效果 - 修正原代码中文本输入框重复定义
class属性的问题,保证.control类生效
- 拖拽逻辑修改
- 遍历所有可拖拽元素绑定拖拽事件,修复原代码仅对第一个控件生效的问题
dragstart阶段记录鼠标点击在拖拽元素内部的偏移量,避免放置时元素左上角与鼠标位置对齐drop阶段计算元素在放置容器内的相对坐标,赋值给元素的left、top样式属性完成定位
完整可运行代码
<style> .toolbox { height: 250px; width: 150px; border: solid 3px #ccc; margin: 10px; display: flex; flex-direction: column; align-items: center; justify-content: center; position: relative; } .edit { width: 140px; } .form { height: 250px; width: 150px; border: solid 3px red; position: relative; } .drop-targets { display: flex; flex-direction: row; justify-content: center; align-items: center; margin: 20px 0; } .drag-over { border: dashed 3px red; } .control { position: absolute; cursor: move; } .hide { display: none; } </style> <div class="drop-targets"> <div id="controls" class="toolbox"> <input type="button" value="Button 1" id="button1" draggable="true" class="control"> <br> <input type="text" value="Edit 1" class="edit control" draggable="true"> </div> <div id="panel" class="form"></div> </div> <script> // 给所有可拖拽元素绑定事件 const items = document.querySelectorAll('.control'); items.forEach(item => { item.addEventListener('dragstart', dragStart); }); function dragStart(e) { e.dataTransfer.setData('text/plain', e.target.id); // 存储鼠标在元素内部的偏移量 e.dataTransfer.setData('offsetX', e.offsetX); e.dataTransfer.setData('offsetY', e.offsetY); setTimeout(() => { e.target.classList.add('hide'); }, 0); } const box = document.querySelector('#panel'); box.addEventListener('dragenter', dragEnter); box.addEventListener('dragover', dragOver); box.addEventListener('dragleave', dragLeave); box.addEventListener('drop', drop); function dragEnter(e) { e.preventDefault(); box.classList.add('drag-over'); } function dragOver(e) { e.preventDefault(); box.classList.add('drag-over'); } function dragLeave(e) { box.classList.remove('drag-over'); } function drop(e) { e.preventDefault(); box.classList.remove('drag-over'); const id = e.dataTransfer.getData('text/plain'); const draggable = document.getElementById(id); // 获取偏移量 const offsetX = parseInt(e.dataTransfer.getData('offsetX')); const offsetY = parseInt(e.dataTransfer.getData('offsetY')); // 计算放置容器的坐标 const panelRect = box.getBoundingClientRect(); // 计算元素在容器内的相对位置 const left = e.clientX - panelRect.left - offsetX; const top = e.clientY - panelRect.top - offsetY; // 设置元素位置 draggable.style.left = `${left}px`; draggable.style.top = `${top}px`; box.appendChild(draggable); draggable.classList.remove('hide'); } </script>
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

