JS拖拽的实现
基本拖拽实现
使用原生JavaScript实现拖拽功能需要监听三个事件:mousedown、mousemove和mouseup。在mousedown事件中记录初始位置,在mousemove事件中计算偏移量并更新元素位置,在mouseup事件中移除事件监听。
const draggable = document.getElementById('draggable');
let isDragging = false;
let offsetX, offsetY;
draggable.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggable.offsetLeft;
offsetY = e.clientY - draggable.offsetTop;
});
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;
});
限制拖拽范围
通过判断元素位置是否超出边界,可以限制拖拽范围。在mousemove事件中添加边界检查逻辑。
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
let left = e.clientX - offsetX;
let top = e.clientY - offsetY;
const maxX = window.innerWidth - draggable.offsetWidth;
const maxY = window.innerHeight - draggable.offsetHeight;
left = Math.max(0, Math.min(left, maxX));
top = Math.max(0, Math.min(top, maxY));
draggable.style.left = `${left}px`;
draggable.style.top = `${top}px`;
});
拖拽手柄实现
有时只需要元素的一部分(如标题栏)可拖拽。通过检查事件目标是否为手柄元素来实现。
const handle = document.getElementById('handle');
handle.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - draggable.offsetLeft;
offsetY = e.clientY - draggable.offsetTop;
});
拖拽性能优化
频繁触发mousemove事件可能影响性能。使用requestAnimationFrame优化位置更新。
let animationId;
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
cancelAnimationFrame(animationId);
animationId = requestAnimationFrame(() => {
draggable.style.left = `${e.clientX - offsetX}px`;
draggable.style.top = `${e.clientY - offsetY}px`;
});
});
拖拽事件兼容性
为支持移动端触摸事件,可以添加touchstart、touchmove和touchend事件监听。注意触摸事件的坐标获取方式不同。
draggable.addEventListener('touchstart', (e) => {
isDragging = true;
const touch = e.touches[0];
offsetX = touch.clientX - draggable.offsetLeft;
offsetY = touch.clientY - draggable.offsetTop;
e.preventDefault();
});
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`;
e.preventDefault();
});
document.addEventListener('touchend', () => {
isDragging = false;
});






