实现可拖拽div松开后沿拖动方向自动滑动的功能及问题排查
问题根因
你当前的甩动逻辑完全错误:KickElement函数中使用元素当前位置与屏幕中心点的坐标差作为移动向量,和你实际的拖拽方向没有任何关联,因此才会出现方向错误、反向移动的问题。
修正思路
- 拖拽过程中记录鼠标的实时位移,松开鼠标时用最后一段的位移数据作为甩动的初速度方向
- 新增定时器管理逻辑,避免多次拖拽生成多个定时器导致运动异常
- 可增加摩擦系数让元素自然减速停止,更符合真实物理效果
完整可运行代码
HTML
<h1>Draggable DIV Element</h1> <p>Click and hold the mouse button down while moving the DIV element</p> <div id="mydiv" class="bothrn"> <div>Click here to move</div> </div>
CSS
.bothrn{ position: absolute; z-index: 9; background-color: #f1f1f1; text-align: center; border: 1px solid #d3d3d3; min-width: 30%; min-height: 60%; cursor: move; border-radius: 4vw; }
JavaScript
//Make the DIV element draggagle: dragElement(document.getElementById("mydiv")); function dragElement(elmnt) { var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; var moveTimer = null; // 存储甩动定时器 var friction = 0.95; // 摩擦系数,值越小减速越快 var velocityX = 0, velocityY = 0; // 甩动初速度 if (document.getElementById(elmnt.id)) { document.getElementById(elmnt.id).onmousedown = dragMouseDown; } else { elmnt.onmousedown = dragMouseDown; } function dragMouseDown(e) { e = e || window.event; e.preventDefault(); // 拖拽开始前清理之前的甩动定时器 if(moveTimer) clearInterval(moveTimer); pos3 = e.clientX; pos4 = e.clientY; document.onmouseup = closeDragElement; document.onmousemove = elementDrag; } function elementDrag(e) { e = e || window.event; e.preventDefault(); pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; pos3 = e.clientX; pos4 = e.clientY; // 实时更新速度值 velocityX = -pos1; velocityY = -pos2; elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; } function closeDragElement() { document.onmouseup = null; document.onmousemove = null; kickElement(); } function kickElement() { moveTimer = setInterval(function () { // 应用摩擦系数减速 velocityX *= friction; velocityY *= friction; // 速度足够小时停止运动 if(Math.abs(velocityX) < 0.1 && Math.abs(velocityY) < 0.1) { clearInterval(moveTimer); return; } elmnt.style.top = (elmnt.offsetTop + velocityY) + 'px'; elmnt.style.left = (elmnt.offsetLeft + velocityX) + 'px'; }, 16); // 16ms约等于60帧,性能更优 } } document.getElementById("mydiv").style.top = "30%"; var meh = document.getElementsByClassName("bothrn"); for (var i = 0; i < meh.length; i++) meh[i].style.left = "35%";
改动说明
- 移除了原逻辑中与屏幕中心相关的错误方向计算代码
- 新增速度变量记录拖拽过程的实时位移,作为甩动的初速度
- 增加定时器管理逻辑,避免多个定时器同时运行导致异常
- 增加摩擦系数实现自然减速效果,替换原有的匀速逻辑
- 将定时器间隔调整为16ms,匹配浏览器60fps的渲染频率,性能更优
内容的提问来源于stack exchange,提问作者kfir ezer
相关产品推荐
相关产品推荐

