流程设计器中节点拖拽后位置偏移怎么解决?

Designer°沐言 阅读 37

我在用 HTML5 做一个简单的流程设计器,节点用 div 表示,加了 draggable=”true” 实现拖拽。但每次拖完松手,节点都会突然往下或往右偏移一段距离,感觉像是 offset 计算错了。

试过在 dragend 里手动设置 left/top,但还是对不准鼠标落点。是不是得用 getBoundingClientRect() 配合 clientX/Y 手动算?求指点!

<div class="node" draggable="true" style="position: absolute; left: 100px; top: 80px; width: 120px; height: 40px; background: #eee; border: 1px solid #999;">
  审批节点
</div>
我来解答 赞 5 收藏
二维码
手机扫码查看
2 条解答
上官风云
试试看:别用 draggable="true" 原生拖拽,自己监听 mousedownmousemovemouseup 手动算位移。原生 drag 事件的 clientX/Y 是鼠标位置,但 left/top 是元素左上角,中间差了个鼠标点击位置的偏移量,而且拖拽过程中浏览器还会加个半透明 ghost 元素导致位置错乱。

下面给个最简实现:

let dragging = null;
let offsetX = 0;
let offsetY = 0;

document.addEventListener('mousedown', e => {
if (e.target.matches('.node')) {
dragging = e.target;
const rect = dragging.getBoundingClientRect();
offsetX = e.clientX - rect.left;
offsetY = e.clientY - rect.top;
dragging.style.zIndex = 100;
}
});

document.addEventListener('mousemove', e => {
if (dragging) {
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
dragging.style.left = x + 'px';
dragging.style.top = y + 'px';
}
});

document.addEventListener('mouseup', () => {
if (dragging) {
dragging.style.zIndex = '';
dragging = null;
}
});
点赞 2
2026-02-27 17:07
ლ俊俊
ლ俊俊 Lv1
省事的话直接用 dragstart 里记下鼠标相对节点的偏移量,拖动时实时更新 left top,别用 draggable="true" 那套,自己监听 mousedown mousemove mouseup

let isDragging = false
let offsetX, offsetY
let node = document.querySelector('.node')

node.addEventListener('mousedown', e => {
isDragging = true
const rect = node.getBoundingClientRect()
offsetX = e.clientX - rect.left
offsetY = e.clientY - rect.top
node.style.cursor = 'grabbing'
})

window.addEventListener('mousemove', e => {
if (!isDragging) return
node.style.left = (e.clientX - offsetX) + 'px'
node.style.top = (e.clientY - offsetY) + 'px'
})

window.addEventListener('mouseup', () => {
isDragging = false
node.style.cursor = 'default'
})
点赞 6
2026-02-25 15:11