当前位置:首页 > 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';
});

封装为可复用插件

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

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;
  // ... 其他代码 ...
}

支持移动端触摸事件

添加触摸事件支持:

js实现拖拽插件

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中实现图片拖拽功能可以通过HTML5的拖放API结合Vue的事件处理来完成。以下是一个完整的实现方法: 基础拖拽实现 为图片元素添加draggable属性并绑定相关事件:…

vue实现皮肤插件

vue实现皮肤插件

实现思路 Vue实现皮肤插件通常通过动态切换CSS变量或类名实现。核心思路是将皮肤样式抽离为独立的CSS文件或变量,通过用户交互或配置切换不同的皮肤主题。 基础实现方案 定义皮肤变量 在全局CSS中…

vue实现功能插件

vue实现功能插件

Vue 功能插件实现方法 插件基本结构 Vue 插件通常需要暴露一个 install 方法,该方法接收 Vue 构造函数作为参数。基本结构如下: const MyPlugin = { insta…

vue能实现拖拽

vue能实现拖拽

Vue 实现拖拽的方法 Vue 可以通过多种方式实现拖拽功能,包括原生 HTML5 的拖拽 API、第三方库如 vuedraggable 或自定义指令。以下是几种常见的实现方式: 使用 HTML5…

前端vue实现拖拽

前端vue实现拖拽

Vue 实现拖拽功能的方法 使用 HTML5 原生拖拽 API HTML5 提供了原生的拖拽 API,可以通过 draggable 属性、dragstart、dragend、dragover 和 dr…

vue实现图片插件

vue实现图片插件

Vue 图片插件实现方案 在 Vue 中实现图片插件通常涉及图片展示、懒加载、预览等功能。以下是几种常见的实现方式: 基础图片组件封装 创建一个可复用的图片组件,支持默认图片、加载失败处理等基础功能…