如何用InteractJs实现拖拽元素跟随触摸/光标移动
问题描述
我用InteractJs在容器内实现了一个受边界限制的拖拽元素,元素默认隐藏,触摸开始时显示。现在想让这个拖拽元素完全跟随光标/触摸位置:
- 首次点击/触摸时直接出现在对应位置
- 拖拽/触摸移动时全程跟随
- 触摸结束后隐藏
尝试过用touchstart的坐标设置transform样式但没成功,求修改代码实现效果。
解决方案
核心是调整元素定位方式,让拖拽元素能基于触摸点精准定位,同时修正InteractJs的拖拽逻辑,让位移计算基于当前触摸点而非初始位置。具体修改如下:
关键调整点
- 定位方式改造:给容器设置相对定位,拖拽元素改为绝对定位,配合
translate(-50%, -50%)让元素居中对齐触摸点,更符合操作直觉。 - 触摸触发时直接定位:在容器的
down事件中,计算触摸点相对于容器的坐标,直接将拖拽元素定位到该位置,并重置位移数据。 - 拖拽移动逻辑简化:拖拽时直接使用InteractJs提供的位移增量更新元素位置,保证跟随流畅。
- 拖拽结束重置状态:隐藏元素的同时重置所有位置相关属性,避免下次触发时位置错乱。
修改后的完整代码
HTML代码
<!DOCTYPE html> <html> <head> <title></title> <script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.17/interact.min.js"></script> <style> body{padding-top:100px;} .container { width:368px; height:120px; background-color:red; margin:0 auto; z-index:2; position: relative; /* 作为绝对定位的参考容器 */ } .draggable { visibility:hidden; height:60px; width:80px; background-color:#fff; position: absolute; /* 改为绝对定位,方便精准控制位置 */ touch-action:none; z-index:1; transform: translate(-50%, -50%); /* 让元素居中对齐触摸点 */ } </style> </head> <body> <div class="container"> <div class="draggable"></div> </div> </body> </html>
JS代码
let dragMoveListener = (event) => { const target = event.target; // 直接使用拖拽增量更新位置 const x = event.dx; const y = event.dy; target.style.transform = `translate(calc(-50% + ${x}px), calc(-50% + ${y}px))`; // 更新位移记录 target.setAttribute('data-x', x); target.setAttribute('data-y', y); } const draggables = document.querySelectorAll(".draggable"); const containers = document.querySelectorAll(".container"); containers.forEach(container => { interact(container).on("down", (e) => { const draggable = container.querySelector('.draggable'); // 计算触摸点相对于容器的坐标 const rect = container.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; // 显示元素并定位到触摸点 draggable.style.visibility = 'visible'; draggable.style.left = `${x}px`; draggable.style.top = `${y}px`; // 重置位移数据 draggable.setAttribute('data-x', 0); draggable.setAttribute('data-y', 0); }); }); draggables.forEach(element => { interact(element) .on("dragend", (e) => { // 隐藏元素并重置所有位置属性 element.style.visibility = 'hidden'; element.style.left = '0'; element.style.top = '0'; element.style.transform = 'translate(-50%, -50%)'; element.setAttribute('data-x', 0); element.setAttribute('data-y', 0); }) .draggable({ onmove: dragMoveListener, modifiers: [ interact.modifiers.restrict({ restriction: 'parent', endOnly: false, // 调整边界计算,适配居中定位的元素 elementRect: { top: 0, left: 0, bottom: 1, right: 1 } }) ] }); });
内容的提问来源于stack exchange,提问作者moogeek
相关产品推荐
相关产品推荐

