/** * @param {Element} eleBar 拖拽触发元素 * @param {Object} options 可选参数 * @returns */ const startDrag = function (eleBar, options) { if (!eleBar) { return; } // 默认数据 const defaults = { target: eleBar, bounding: window, edgeLock: true, onMove: function () {}, onEnd: function () {}, }; options = options || {}; const params: any = {}; for (const key in defaults) { if (typeof options[key] != 'undefined') { params[key] = options[key]; } else { params[key] = defaults[key]; } } // 拖拽元素 const eleTarget = params.target; // 限制范围 const bounding = params.bounding; let objBounding = bounding; // 事件类型处理 let objEventType = { start: 'mousedown', move: 'mousemove', end: 'mouseup', }; if ('ontouchstart' in document) { objEventType = { start: 'touchstart', move: 'touchmove', end: 'touchend', }; } // 坐标存储数据 const store: any = {}; eleBar.addEventListener(objEventType.start, function (event) { // IE 拖拽可能拖不动的处理 if (!window.WeakMap || typeof document.msHidden != 'undefined') { event.preventDefault(); } // 兼顾移动端 if (event.touches && event.touches.length) { event = event.touches[0]; } store.y = event.pageY; store.x = event.pageX; store.isMoving = true; store.top = parseFloat(getComputedStyle(eleTarget).top) || 0; store.left = parseFloat(getComputedStyle(eleTarget).left) || 0; if (params.edgeLock === true && bounding) { if (bounding === window) { objBounding = { left: 0, top: 0, bottom: innerHeight, right: Math.min(innerWidth, document.documentElement.clientWidth), }; } else if (bounding.tagName) { objBounding = bounding.getBoundingClientRect(); } // 拖拽元素的 bounding 位置 const objBoundingTarget = eleTarget.getBoundingClientRect(); // 可移动范围 store.range = { y: [objBounding.top - objBoundingTarget.top, objBounding.bottom - objBoundingTarget.bottom], x: [objBounding.left - objBoundingTarget.left, objBounding.right - objBoundingTarget.right], }; } }); document.addEventListener( objEventType.move, function (event: any) { if (store.isMoving) { event.preventDefault(); // 兼顾移动端 if (event.touches && event.touches.length) { event = event.touches[0]; } let distanceY = event.pageY - store.y; let distanceX = event.pageX - store.x; // 边界的判断与chuli if (params.edgeLock === true && bounding) { const minX = Math.min.apply(null, store.range.x); const maxX = Math.max.apply(null, store.range.x); const minY = Math.min.apply(null, store.range.y); const maxY = Math.max.apply(null, store.range.y); if (distanceX < minX) { distanceX = minX; } else if (distanceX > maxX) { distanceX = maxX; } if (distanceY < minY) { distanceY = minY; } else if (distanceY > maxY) { distanceY = maxY; } } const top = store.top + distanceY; const left = store.left + distanceX; eleTarget.style.top = top + 'px'; eleTarget.style.left = left + 'px'; // 回调 params.onMove(left, top); } }, { passive: false, }, ); document.addEventListener(objEventType.end, function () { if (store.isMoving) { store.isMoving = false; params.onEnd(); } }); }; export default startDrag;