用 interact.js 实现拖拽时元素位置偏移怎么办?
我在用 interact.js 做一个可拖拽的卡片组件,但每次拖动时元素都会突然跳一下,感觉位置偏移了。我试过调整 dragMoveListener 里的 translate 值,但还是不对。
这是我的拖拽处理代码:
interact('.draggable').draggable({
listeners: {
move(event) {
const target = event.target;
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = <code>translate(${x}px, ${y}px)</code>;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
}
});
是不是哪里没设置对?为啥一拖就跳到鼠标左上角去了?
你遇到的是 interact.js 最经典的"初始位置跳跃"问题。问题的根源在于:你的元素在页面上可能本身就有定位(比如用了 position: absolute/relative,或者有 margin),但你的 data-x 和 data-y 初始值都是 0。当你第一次拖动时,transform 会立刻把元素强制移动到 (0, 0) 这个位置,所以就"跳"了一下。
说直白点,就是元素当前的实际位置和你记录的位置不同步。
解决办法有两个方向,我一个个说。
第一种方式,也是最推荐的,是在拖拽开始时同步一下初始位置。你需要监听 start 事件:
第二种方式更简单粗暴,直接在 CSS 和 HTML 里把初始状态设好。确保你的元素一开始就有正确的 data-x 和 data-y 值,CSS 里也不要有额外的定位干扰:
然后 HTML 里直接写好初始值:
还有一种情况会导致跳动,就是你的元素用了 position: absolute 同时又设置 top/left,这时候 transform 会基于元素的原始位置叠加。解决办法是要么只用 transform 控制位置(把 top/left 去掉),要么在计算时把它们也算进去。
顺便说一句,你的代码里那个模板字符串写错了,应该是反引号不是
标签。正确写法是:
如果上面这些还是不行,把你元素的 CSS 发出来看看,可能是定位方式的问题。我猜测大概率是第一种情况,初始位置没同步。