From 8a8a1fc4044a26841775c07414dc6da0368d1ab4 Mon Sep 17 00:00:00 2001 From: yutent Date: Wed, 29 Mar 2023 17:30:09 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E6=8B=96=E6=8B=BD=E6=8F=92?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/drag/core.js | 137 +++++++++++++++++++++++++++++++++++++++++++++ src/form/switch.js | 2 +- 2 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/drag/core.js diff --git a/src/drag/core.js b/src/drag/core.js new file mode 100644 index 0000000..c0511bb --- /dev/null +++ b/src/drag/core.js @@ -0,0 +1,137 @@ +/** + * 拖拽插件的核心部分 + * @author yutent + * @date 2019/08/23 19:41:21 + */ + +import { $, bind, unbind, fire } from '@bd/core' + +const DEF_OPT = { + axis: '', // x | y | xy 拖拽方向 + limit: false, // false | window | parent 拖拽范围 + overflow: true // 是否可拖拽出可视区外 +} + +export default class Drag { + constructor(elem) { + this.$elem = elem + + this.#init() + } + + #init() { + this.$elem.style.transform = '' + var { x, y } = this.$elem.getBoundingClientRect() + // _x, _y是位移,用于数据修正 + this.pos = { x, y, _x: 0, _y: 0 } + } + + // drag by + by(node, opt = {}) { + this.$drag = node + this.opt = Object.assign(Object.create(null), DEF_OPT, opt) + + // + if (this.opt.limit !== false) { + this.opt.overflow = false + } + + // 鼠标状态图标 + node.style.cursor = 'move' + + this._handleResize = bind(window, 'resize', this.#init.bind(this)) + + // let + this._handleMousedown = bind(node, 'mousedown', ev => { + if (this.disabled) { + return + } + var bcr = this.$elem.getBoundingClientRect() + + /* 修正由于页面有滚动距离,导致拖拽位移计算不正确的情况 */ + if (bcr.x - this.pos._x !== this.pos.x) { + this.pos.x = bcr.x - this.pos._x + } + if (bcr.y - this.pos._y !== this.pos.y) { + this.pos.y = bcr.y - this.pos._y + } + + let mx = ev.pageX + let my = ev.pageY + + let ww = document.documentElement.clientWidth + let wh = document.documentElement.clientHeight + + let tw = bcr.width + let th = bcr.height + + //限制区域, 4个值依次是: 上, 右, 下, 左 + let limit = [0, ww - tw, wh - th, 0] + if (this.opt.limit === 'parent') { + let pbcr = this.$elem.parentNode.getBoundingClientRect() + limit = [pbcr.top, pbcr.right - tw, pbcr.bottom - th, pbcr.left] + } + + let handleMove = bind(document, 'mousemove', ev => { + // 防止拖动到边缘时导致页面滚动 + ev.preventDefault() + + let _x = ev.pageX - mx + (bcr.x - this.pos.x) + let _y = ev.pageY - my + (bcr.y - this.pos.y) + + // 将另外一个方向的值清零来实现单向拖拽 + if (this.opt.axis === 'x') { + _y = 0 + } + if (this.opt.axis === 'y') { + _x = 0 + } + + // 限制不可拖拽出指定区域(可视区或者父容器) + if (this.opt.overflow === false) { + if (_x < limit[3] - this.pos.x) { + _x = limit[3] - this.pos.x + } else if (_x > limit[1] - this.pos.x) { + _x = limit[1] - this.pos.x + } + + if (_y < limit[0] - this.pos.y) { + _y = limit[0] - this.pos.y + } else if (_y > limit[2] - this.pos.y) { + _y = limit[2] - this.pos.y + } + } + this.pos._x = _x + this.pos._y = _y + fire(this.$elem, 'dragging', { + offset: { + x: this.pos.x + _x, + y: this.pos.y + _y + }, + moved: { x: _x, y: _y } + }) + this.$elem.style.transform = `translate(${_x}px, ${_y}px)` + }) + + let handleUp = bind(document, 'mouseup', ev => { + fire(this.$elem, 'dragged', { + offset: { + x: this.pos.x + this.pos._x, + y: this.pos.y + this.pos._y + }, + moved: { x: this.pos._x, y: this.pos._y } + }) + + unbind(document, 'mousemove', handleMove) + unbind(document, 'mouseup', handleUp) + }) + }) + + return this + } + + destroy() { + unbind(window, 'resize', this._handleResize) + unbind(this.$drag, 'mousedown', this._handleMousedown) + } +} diff --git a/src/form/switch.js b/src/form/switch.js index 1e2385d..b6d2451 100644 --- a/src/form/switch.js +++ b/src/form/switch.js @@ -201,7 +201,7 @@ class Switch extends Component { @click=${this.handleClick} @keydown=${this.handleClick} > - + ` }