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

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

相关文章

uniapp插件收益

uniapp插件收益

uniapp插件收益来源 uniapp插件的收益主要来自开发者将插件发布到DCloud插件市场后的销售分成。开发者可以设置插件的价格,用户购买后,开发者获得相应收入。 插件定价策略 插件的定价根据…

uniapp市场插件

uniapp市场插件

uniapp市场插件概览 uniapp的插件市场(DCloud插件市场)提供了丰富的插件资源,涵盖UI组件、功能扩展、模板、原生插件等类别,帮助开发者快速实现复杂功能。以下是常见插件类型及推荐:…

vue能实现拖拽

vue能实现拖拽

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

php 插件实现

php 插件实现

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

vue实现盒子拖拽

vue实现盒子拖拽

实现盒子拖拽的基本思路 在Vue中实现盒子拖拽功能,可以通过监听鼠标事件(mousedown、mousemove、mouseup)来实现。核心逻辑是记录拖拽起始位置,计算位移差值,并更新盒子的位置。…

vue怎么实现拖拽

vue怎么实现拖拽

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