js实现拖拽插件
实现拖拽功能的基本原理
拖拽功能的核心是监听鼠标事件(mousedown、mousemove、mouseup),通过计算鼠标移动距离来更新元素位置。以下是一个基础实现示例:
const draggableElement = document.getElementById('drag-element');
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';
});
封装为可复用插件
将基础功能封装为插件形式,支持配置选项和事件回调:

class DragPlugin {
constructor(element, options = {}) {
this.element = element;
this.options = {
handle: null,
onStart: () => {},
onMove: () => {},
onEnd: () => {},
...options
};
this.isDragging = false;
this.offset = { x: 0, y: 0 };
this.init();
}
init() {
const handle = this.options.handle
? this.element.querySelector(this.options.handle)
: this.element;
handle.style.cursor = 'grab';
handle.addEventListener('mousedown', this.startDrag.bind(this));
document.addEventListener('mousemove', this.onDrag.bind(this));
document.addEventListener('mouseup', this.endDrag.bind(this));
}
startDrag(e) {
this.isDragging = true;
const rect = this.element.getBoundingClientRect();
this.offset = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
this.options.onStart();
this.element.style.cursor = 'grabbing';
}
onDrag(e) {
if (!this.isDragging) return;
this.element.style.left = `${e.clientX - this.offset.x}px`;
this.element.style.top = `${e.clientY - this.offset.y}px`;
this.options.onMove();
}
endDrag() {
this.isDragging = false;
this.options.onEnd();
this.element.style.cursor = 'grab';
}
}
使用示例
<div id="box" style="position: absolute; width: 100px; height: 100px; background: red;"></div>
<script>
new DragPlugin(document.getElementById('box'), {
onStart: () => console.log('拖动开始'),
onMove: () => console.log('拖动中'),
onEnd: () => console.log('拖动结束')
});
</script>
支持拖拽限制边界
添加边界限制功能,防止元素被拖出可视区域:

class DragPlugin {
// ... 其他代码保持不变 ...
onDrag(e) {
if (!this.isDragging) return;
let x = e.clientX - this.offset.x;
let y = e.clientY - this.offset.y;
// 边界检查
const rect = this.element.getBoundingClientRect();
const maxX = window.innerWidth - rect.width;
const maxY = window.innerHeight - rect.height;
x = Math.max(0, Math.min(x, maxX));
y = Math.max(0, Math.min(y, maxY));
this.element.style.left = `${x}px`;
this.element.style.top = `${y}px`;
this.options.onMove();
}
}
支持拖拽元素层级管理
自动将拖拽元素置于最上层:
startDrag(e) {
this.isDragging = true;
// 获取当前最高z-index
const maxZ = Math.max(...Array.from(document.querySelectorAll('*'))
.map(el => parseInt(window.getComputedStyle(el).zIndex) || 0));
this.element.style.zIndex = maxZ + 1;
// ... 其他代码 ...
}
支持移动端触摸事件
添加触摸事件支持:
init() {
const handle = this.options.handle
? this.element.querySelector(this.options.handle)
: this.element;
handle.style.touchAction = 'none'; // 防止默认触摸行为
handle.addEventListener('mousedown', this.startDrag.bind(this));
handle.addEventListener('touchstart', this.handleTouchStart.bind(this));
document.addEventListener('mousemove', this.onDrag.bind(this));
document.addEventListener('touchmove', this.handleTouchMove.bind(this), { passive: false });
document.addEventListener('mouseup', this.endDrag.bind(this));
document.addEventListener('touchend', this.endDrag.bind(this));
}
handleTouchStart(e) {
e.preventDefault();
const touch = e.touches[0];
this.startDrag({
clientX: touch.clientX,
clientY: touch.clientY
});
}
handleTouchMove(e) {
e.preventDefault();
const touch = e.touches[0];
this.onDrag({
clientX: touch.clientX,
clientY: touch.clientY
});
}






