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';
});
添加边界限制
为防止元素被拖出可视区域,可以添加边界检查:

document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
let x = e.clientX - offsetX;
let y = e.clientY - offsetY;
// 限制在窗口范围内
x = Math.max(0, Math.min(x, window.innerWidth - draggable.offsetWidth));
y = Math.max(0, Math.min(y, window.innerHeight - draggable.offsetHeight));
draggable.style.left = `${x}px`;
draggable.style.top = `${y}px`;
});
支持触摸设备
为支持移动设备触摸操作,需要添加触摸事件处理:
draggable.addEventListener('touchstart', (e) => {
isDragging = true;
const touch = e.touches[0];
offsetX = touch.clientX - draggable.getBoundingClientRect().left;
offsetY = touch.clientY - draggable.getBoundingClientRect().top;
});
document.addEventListener('touchmove', (e) => {
if (!isDragging) return;
const touch = e.touches[0];
let x = touch.clientX - offsetX;
let y = touch.clientY - offsetY;
x = Math.max(0, Math.min(x, window.innerWidth - draggable.offsetWidth));
y = Math.max(0, Math.min(y, window.innerHeight - draggable.offsetHeight));
draggable.style.left = `${x}px`;
draggable.style.top = `${y}px`;
});
document.addEventListener('touchend', () => {
isDragging = false;
});
使用CSS优化拖动体验
添加CSS样式提升拖动时的视觉效果:

#draggable {
position: absolute;
cursor: grab;
user-select: none;
touch-action: none;
}
#draggable:active {
cursor: grabbing;
}
实现拖动排序功能
扩展实现拖动排序功能,需要跟踪元素位置变化:
const container = document.getElementById('container');
const items = Array.from(container.children);
let draggedItem = null;
items.forEach(item => {
item.addEventListener('dragstart', () => {
draggedItem = item;
setTimeout(() => item.classList.add('dragging'), 0);
});
item.addEventListener('dragend', () => {
item.classList.remove('dragging');
draggedItem = null;
});
});
container.addEventListener('dragover', e => {
e.preventDefault();
const afterElement = getDragAfterElement(container, e.clientY);
if (afterElement) {
container.insertBefore(draggedItem, afterElement);
} else {
container.appendChild(draggedItem);
}
});
function getDragAfterElement(container, y) {
const elements = [...container.querySelectorAll('.item:not(.dragging)')];
return elements.reduce((closest, child) => {
const box = child.getBoundingClientRect();
const offset = y - box.top - box.height / 2;
if (offset < 0 && offset > closest.offset) {
return { offset, element: child };
} else {
return closest;
}
}, { offset: Number.NEGATIVE_INFINITY }).element;
}
使用HTML5 Drag API
利用原生HTML5拖放API实现更标准的拖动:
<div id="container">
<div class="item" draggable="true">Item 1</div>
<div class="item" draggable="true">Item 2</div>
</div>
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('dragstart', () => {
item.classList.add('dragging');
});
item.addEventListener('dragend', () => {
item.classList.remove('dragging');
});
});
container.addEventListener('dragover', e => {
e.preventDefault();
const afterElement = getDragAfterElement(container, e.clientY);
const dragging = document.querySelector('.dragging');
if (afterElement) {
container.insertBefore(dragging, afterElement);
} else {
container.appendChild(dragging);
}
});






