当前位置:首页 > JavaScript

js实现拖拽插件

2026-01-31 00:10:31JavaScript

实现拖拽功能的基本原理

拖拽功能的核心是监听鼠标事件(mousedownmousemovemouseup),通过计算鼠标移动距离来更新元素位置。以下是一个基础实现示例:

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';
});

封装为可复用插件

将基础功能封装为插件形式,支持配置选项和事件回调:

js实现拖拽插件

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>

支持拖拽限制边界

添加边界限制功能,防止元素被拖出可视区域:

js实现拖拽插件

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
  });
}

标签: 插件拖拽
分享给朋友:

相关文章

vue实现拖拽实现布局

vue实现拖拽实现布局

Vue 实现拖拽布局的方法 使用 Vue.Draggable 库 Vue.Draggable 是基于 Sortable.js 的 Vue 组件,适合实现列表或网格的拖拽排序。 安装依赖: npm…

vue实现carousel拖拽

vue实现carousel拖拽

实现拖拽轮播的基本思路 在Vue中实现可拖拽的Carousel组件需要结合触摸事件(touchstart、touchmove、touchend)和鼠标事件(mousedown、mousemove、mo…

vue插件实现联动

vue插件实现联动

Vue 插件实现联动的方法 使用全局事件总线 在 Vue 中可以通过创建一个全局事件总线来实现组件间的联动。首先创建一个新的 Vue 实例作为事件总线。 // event-bus.js import…

vue分页插件实现

vue分页插件实现

Vue 分页插件实现方法 使用现成组件库(推荐) Element UI、Ant Design Vue 等主流库已提供成熟分页组件,可直接集成: <template> <…

php 插件实现

php 插件实现

PHP 插件实现方法 PHP 插件可以通过多种方式实现,具体取决于插件的用途和功能需求。以下是一些常见的实现方法: 使用钩子(Hooks)和过滤器(Filters) 钩子和过滤器是一种常见的插件架…

js实现图片拖拽

js实现图片拖拽

实现图片拖拽的基本步骤 HTML 结构需要包含可拖拽的图片元素,并设置 draggable 属性为 true: <img id="dragImage" src="image.jpg" drag…