拖拽看板卡片到其他列时,位置总是偏移怎么办?
我在实现看板卡片拖拽时遇到个怪问题,当把卡片拖到不同宽度的列时,它的垂直位置会突然跳动,看起来特别不连贯。
我试过在dragover事件里用客户端坐标计算top值,但不同列宽度导致定位不准。比如左边列有侧边距,右边列没有,拖过去时卡片会贴到左边框。代码大概这样写的:
let dropY = e.clientY - board.offsetTop;
cards.forEach(card => {
const cardTop = card.offsetTop;
if(dropY < cardTop + 20) {
target.appendChild(draggingCard, card);
break;
}
});
后来我把board.offsetTop改成了e.target.getBoundingClientRect().top,结果卡片直接飞到页面顶部去了。是不是要考虑列容器的padding或者border-box?
board.offsetTop是相对文档的偏移,但你用e.clientY减它,又混用了e.target.getBoundingClientRect().top这种相对视口的值,自然乱套。关键点是:所有坐标计算必须基于同一个参考系,要么全用
getBoundingClientRect(),要么全用offsetTop+ 累加父级偏移,别混着来。推荐用
getBoundingClientRect(),因为更稳,不受父级padding、border影响:这样
dropY和cardTop都是相对于board的内部纵坐标,跟列宽、padding、border 都没关系,不会跳动。另外你代码里
target.appendChild(draggingCard, card)这个用法不对,appendChild只能加到末尾,要插入到某个节点前应该用insertBefore:再顺手优化一下:别每次
dragover都遍历所有卡片,缓存下卡片的top值,或者用Element.closest('.column')判断当前列,减少计算开销。getBoundingClientRect()是对的,但要算上父容器的位置。试试这个:这样就解决了不同列宽度带来的偏移问题。记得检查下是否有额外的 margin 或 padding 影响位置。