js 实现 拖动
原生 JavaScript 实现拖动功能
监听鼠标事件
为需要拖动的元素添加 mousedown 事件监听器,记录初始位置和鼠标位置。在 mousemove 事件中计算偏移量并更新元素位置,最后在 mouseup 事件中移除监听器。
const draggable = document.getElementById('draggable');
let isDragging = false;
let offsetX, offsetY;
draggable.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggable.getBoundingClientRect().left;
offsetY = e.clientY - draggable.getBoundingClientRect().top;
draggable.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
draggable.style.left = `${e.clientX - offsetX}px`;
draggable.style.top = `${e.clientY - offsetY}px`;
});
document.addEventListener('mouseup', () => {
isDragging = false;
draggable.style.cursor = 'grab';
});
CSS 准备
确保目标元素已设置 position: absolute 或 position: relative,并添加基础样式:
#draggable {
position: absolute;
cursor: grab;
user-select: none;
}
使用 HTML5 Drag API 实现
设置可拖动属性
通过 draggable="true" 标记元素,监听 dragstart 事件设置传输数据:

const draggable = document.getElementById('draggable');
draggable.draggable = true;
draggable.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', e.target.id);
e.target.classList.add('dragging');
});
处理放置区域
为放置区域监听 dragover 和 drop 事件:
const dropZone = document.getElementById('dropzone');
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
const id = e.dataTransfer.getData('text/plain');
const draggedElement = document.getElementById(id);
e.target.appendChild(draggedElement);
draggedElement.classList.remove('dragging');
});
触摸屏适配
添加触摸事件支持 扩展原生实现以支持触摸设备:

draggable.addEventListener('touchstart', (e) => {
const touch = e.touches[0];
isDragging = true;
offsetX = touch.clientX - draggable.getBoundingClientRect().left;
offsetY = touch.clientY - draggable.getBoundingClientRect().top;
});
document.addEventListener('touchmove', (e) => {
if (!isDragging) return;
const touch = e.touches[0];
draggable.style.left = `${touch.clientX - offsetX}px`;
draggable.style.top = `${touch.clientY - offsetY}px`;
});
document.addEventListener('touchend', () => {
isDragging = false;
});
性能优化建议
使用 transform 替代 top/left 修改元素位置时优先使用 CSS transform 属性以提高性能:
// 替换原有的 style.left/top 设置
draggable.style.transform = `translate(${e.clientX - offsetX}px, ${e.clientY - offsetY}px)`;
节流处理 对 mousemove 事件进行节流控制:
function throttle(fn, delay) {
let lastCall = 0;
return function(...args) {
const now = new Date().getTime();
if (now - lastCall < delay) return;
lastCall = now;
return fn(...args);
};
}
document.addEventListener('mousemove', throttle((e) => {
if (!isDragging) return;
// 更新位置逻辑
}, 16)); // 约60fps






