js 实现拖拽
实现拖拽的基本步骤
拖拽功能通常涉及三个主要事件:mousedown、mousemove 和 mouseup。以下是实现拖拽的核心逻辑。
初始化拖拽元素
为需要拖拽的元素添加 mousedown 事件监听器,记录初始位置。
const draggableElement = document.getElementById('draggable');
let isDragging = false;
let offsetX, offsetY;
draggableElement.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggableElement.getBoundingClientRect().left;
offsetY = e.clientY - draggableElement.getBoundingClientRect().top;
draggableElement.style.cursor = 'grabbing';
});
处理拖拽移动
在 mousemove 事件中更新元素的位置,确保鼠标移动时元素跟随。
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
draggableElement.style.left = `${e.clientX - offsetX}px`;
draggableElement.style.top = `${e.clientY - offsetY}px`;
});
结束拖拽
在 mouseup 事件中重置拖拽状态,恢复光标样式。
document.addEventListener('mouseup', () => {
isDragging = false;
draggableElement.style.cursor = 'grab';
});
完整代码示例
以下是一个完整的拖拽实现示例,包含 HTML 和 CSS 部分。
HTML 结构
<div id="draggable" style="width: 100px; height: 100px; background: blue; position: absolute; cursor: grab;"></div>
JavaScript 实现
const draggableElement = document.getElementById('draggable');
let isDragging = false;
let offsetX, offsetY;
draggableElement.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggableElement.getBoundingClientRect().left;
offsetY = e.clientY - draggableElement.getBoundingClientRect().top;
draggableElement.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
draggableElement.style.left = `${e.clientX - offsetX}px`;
draggableElement.style.top = `${e.clientY - offsetY}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
draggableElement.style.cursor = 'grab';
});
注意事项
- 元素定位:拖拽元素必须设置为
position: absolute或position: relative,否则left和top属性无效。 - 性能优化:频繁触发
mousemove事件可能影响性能,必要时可使用防抖(debounce)或节流(throttle)。 - 触摸屏支持:如需支持触摸设备,需额外监听
touchstart、touchmove和touchend事件。
触摸屏支持扩展
为支持触摸设备,可扩展如下代码:

draggableElement.addEventListener('touchstart', (e) => {
isDragging = true;
const touch = e.touches[0];
offsetX = touch.clientX - draggableElement.getBoundingClientRect().left;
offsetY = touch.clientY - draggableElement.getBoundingClientRect().top;
});
document.addEventListener('touchmove', (e) => {
if (!isDragging) return;
const touch = e.touches[0];
draggableElement.style.left = `${touch.clientX - offsetX}px`;
draggableElement.style.top = `${touch.clientY - offsetY}px`;
});
document.addEventListener('touchend', () => {
isDragging = false;
});






