UNPKG

ele-drag

Version:

一个简单易用的js拖动库

283 lines (204 loc) 5.97 kB
# Dragable.js - 轻量级跨平台拖动库 ## 简介 Dragable.js 是一个简单易用的 JavaScript 拖动库,支持移动端和电脑端触摸/鼠标事件。它通过扩展 HTMLElement 原型提供了直观的 API,无需复杂配置即可实现元素的拖动功能。 ## 安装与引入 ### CDN 引入 ```html <!-- 通过 unpkg 引入 --> <script src="https://unpkg.com/dragable-js"></script> <!-- 或通过 jsdelivr 引入 --> <script src="https://cdn.jsdelivr.net/npm/dragable-js"></script> ``` ### npm 安装 ```bash npm install dragable-js ``` 然后通过模块系统引入: ```javascript import 'dragable-js'; // 全局注册 // 或 import { enableDrag, disableDrag } from 'dragable-js'; // 按需引入 ``` ## 基本使用 ### 启用拖动 ```javascript // 获取元素 const element = document.getElementById('drag-me'); // 启用拖动 element.enableDrag(); ``` ### 禁用拖动 ```javascript // 禁用拖动 element.disableDrag(); ``` ## 高级配置 ### 拖动限制 你可以通过 CSS 或 JavaScript 限制拖动范围: ```css #drag-me { position: absolute; /* 限制在父容器内拖动 */ left: 0; top: 0; right: 0; bottom: 0; margin: auto; width: 100px; height: 100px; } ``` ### 自定义拖动句柄 如果你想只在特定子元素上触发拖动: ```javascript const handle = element.querySelector('.drag-handle'); handle.addEventListener('mousedown', (e) => { e.preventDefault(); element.enableDrag(); }); document.addEventListener('mouseup', () => { element.disableDrag(); }); ``` ## 事件系统 Dragable.js 提供了完整的事件生命周期: ### dragstart 拖动开始时触发 ```javascript element.addEventListener('dragstart', (e) => { console.log('开始拖动', e.detail); // e.detail 包含 { x, y } 起始坐标 }); ``` ### dragmove 拖动过程中持续触发 ```javascript element.addEventListener('dragmove', (e) => { console.log('拖动中', e.detail); // e.detail 包含 { x, y, left, top } 当前坐标和位置 }); ``` ### dragend 拖动结束时触发 ```javascript element.addEventListener('dragend', () => { console.log('拖动结束'); }); ``` ## 样式定制 当元素被拖动时,会自动添加 `dragging` 类,你可以利用这个类添加视觉效果: ```css .dragging { opacity: 0.8; cursor: grabbing; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); transition: none; /* 拖动时禁用过渡效果 */ } /* 拖动句柄样式 */ .drag-handle { cursor: grab; } .drag-handle:active { cursor: grabbing; } ``` ## 最佳实践 ### 1. 性能优化 对于大量可拖动元素,建议: ```javascript // 批量启用拖动 document.querySelectorAll('.draggable-item').forEach(item => { item.enableDrag(); }); // 使用事件委托处理拖动事件 document.addEventListener('dragmove', (e) => { if (e.target.classList.contains('important-item')) { // 特殊处理 } }); ``` ### 2. 移动端适配 确保添加以下 meta 标签防止浏览器默认行为: ```html <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> ``` ### 3. 无障碍访问 为可拖动元素添加 ARIA 属性: ```html <div id="drag-me" aria-grabbed="false" tabindex="0"> 可拖动元素 </div> ``` 并通过 JavaScript 更新状态: ```javascript element.addEventListener('dragstart', () => { element.setAttribute('aria-grabbed', 'true'); }); element.addEventListener('dragend', () => { element.setAttribute('aria-grabbed', 'false'); }); ``` ## API 参考 ### HTMLElement 原型方法 | 方法 | 描述 | 示例 | |------|------|------| | `enableDrag()` | 启用元素拖动功能 | `element.enableDrag()` | | `disableDrag()` | 禁用元素拖动功能 | `element.disableDrag()` | ### 自定义事件 | 事件 | 触发时机 | 事件详情 | |------|----------|----------| | `dragstart` | 拖动开始时触发 | `{ x, y }` 起始坐标 | | `dragmove` | 拖动过程中持续触发 | `{ x, y, left, top }` 当前坐标和位置 | | `dragend` | 拖动结束时触发 | 无 | ## 常见问题 ### Q: 拖动时页面也跟着滚动怎么办? A: 确保在可滚动容器中使用,或添加以下 CSS: ```css body { overflow: hidden; } ``` ### Q: 如何限制拖动范围? A: 在 `dragmove` 事件中检查并修正位置: ```javascript element.addEventListener('dragmove', (e) => { const { left, top } = e.detail; const maxX = window.innerWidth - element.offsetWidth; const maxY = window.innerHeight - element.offsetHeight; element.style.left = `${Math.max(0, Math.min(left, maxX))}px`; element.style.top = `${Math.max(0, Math.min(top, maxY))}px`; }); ``` ### Q: 如何实现磁贴吸附效果? A: 在 `dragend` 事件中处理: ```javascript element.addEventListener('dragend', () => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; // 找到最近的吸附点 const snapPoints = [...]; // 你的吸附点数组 const closest = snapPoints.reduce((prev, curr) => { const prevDist = Math.hypot(prev.x - centerX, prev.y - centerY); const currDist = Math.hypot(curr.x - centerX, curr.y - centerY); return currDist < prevDist ? curr : prev; }); // 动画到吸附点 element.style.transition = 'all 0.3s ease'; element.style.left = `${closest.x - rect.width / 2}px`; element.style.top = `${closest.y - rect.height / 2}px`; setTimeout(() => { element.style.transition = ''; }, 300); }); ``` ## 版本更新 ### v1.0.1 - 修复了移动端多点触控的问题 - 提高了事件处理的性能 ### v1.0.0 - 初始发布版本 - 支持基础拖动功能 - 跨平台触摸/鼠标事件支持 ## 许可证 MIT License - 免费用于个人和商业项目