From 3ccabfbe449a691371f0390e15f2ff81dbe3cb6a Mon Sep 17 00:00:00 2001 From: khuntoriia <120667115@qq.com> Date: Fri, 22 Jul 2022 11:31:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E9=80=89=E4=BC=98=E5=8C=96=E5=8F=8A?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D=20(#196)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(stage): 支持绝对定位,固定定位,组内元素按住shift键进行多选拖拽能力 * feat(stage): 使用moveable.helper接管moveable target的更新,针对弹窗场景引入业务方方法进行校准 * feat(stage): 将多选逻辑封装到StageMultiDragResize * fix(stage): 修复多选target元素无法映射到drag虚拟元素的问题 * feat(stage): 多选拖拽完成后将更新的位置信息暴露给上层业务方 * fix(stage): 删除多余的成员变量 Co-authored-by: parisma --- packages/stage/src/StageCore.ts | 4 ++ packages/stage/src/StageDragResize.ts | 6 --- packages/stage/src/StageMultiDragResize.ts | 49 +++++++++++++++++----- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts index 20cee786..ae20b6c9 100644 --- a/packages/stage/src/StageCore.ts +++ b/packages/stage/src/StageCore.ts @@ -141,6 +141,10 @@ export default class StageCore extends EventEmitter { .on('sort', (data: UpdateEventData) => { setTimeout(() => this.emit('sort', data)); }); + + this.multiDr.on('update', (data: UpdateEventData) => { + setTimeout(() => this.emit('update', data)); + }); } public getElementsFromPoint(event: MouseEvent) { diff --git a/packages/stage/src/StageDragResize.ts b/packages/stage/src/StageDragResize.ts index 4bcb02e0..e7cc91c8 100644 --- a/packages/stage/src/StageDragResize.ts +++ b/packages/stage/src/StageDragResize.ts @@ -53,14 +53,8 @@ export default class StageDragResize extends EventEmitter { public target?: HTMLElement; /** 目标节点在蒙层中的占位节点 */ public dragEl?: HTMLDivElement; - /** 多选:目标节点组 */ - public targetList: HTMLElement[] = []; - /** 多选:目标节点在蒙层中的占位节点组 */ - public dragElList: HTMLDivElement[] = []; /** Moveable拖拽类实例 */ public moveable?: Moveable; - /** Moveable多选拖拽类实例 */ - public moveableForMulti?: Moveable; /** 水平参考线 */ public horizontalGuidelines: number[] = []; /** 垂直参考线 */ diff --git a/packages/stage/src/StageMultiDragResize.ts b/packages/stage/src/StageMultiDragResize.ts index ae93ab94..6d66ee89 100644 --- a/packages/stage/src/StageMultiDragResize.ts +++ b/packages/stage/src/StageMultiDragResize.ts @@ -25,7 +25,7 @@ import { DRAG_EL_ID_PREFIX } from './const'; import StageCore from './StageCore'; import StageMask from './StageMask'; import { StageDragResizeConfig } from './types'; -import { getTargetElStyle } from './util'; +import { calcValueByFontsize, getTargetElStyle } from './util'; export default class StageMultiDragResize extends EventEmitter { public core: StageCore; public mask: StageMask; @@ -88,7 +88,7 @@ export default class StageMultiDragResize extends EventEmitter { useRender: false, createAuto: true, }); - const frames: { left: number; top: number; dragLeft: number; dragTop: number; id: string }[] = []; + const frames: { left: number; top: number; id: string }[] = []; this.moveableForMulti .on('dragGroupStart', (params) => { const { events } = params; @@ -96,15 +96,13 @@ export default class StageMultiDragResize extends EventEmitter { // 记录拖动前快照 events.forEach((ev) => { // 实际目标元素 - const matchEventTarget = this.targetList.find((targetItem) => targetItem.id === ev.target.id.split('_')[2]); - // 蒙层虚拟元素(对于在组内的元素拖动时的相对位置不同,因此需要分别记录) - const dragEventTarget = ev.target as HTMLDivElement; - if (!matchEventTarget || !dragEventTarget) return; + const matchEventTarget = this.targetList.find( + (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''), + ); + if (!matchEventTarget) return; frames.push({ left: matchEventTarget.offsetLeft, top: matchEventTarget.offsetTop, - dragLeft: dragEventTarget.offsetLeft, - dragTop: dragEventTarget.offsetTop, id: matchEventTarget.id, }); }); @@ -113,9 +111,13 @@ export default class StageMultiDragResize extends EventEmitter { const { events } = params; // 拖动过程更新 events.forEach((ev) => { - const frameSnapShot = frames.find((frameItem) => frameItem.id === ev.target.id.split('_')[2]); + const frameSnapShot = frames.find( + (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''), + ); if (!frameSnapShot) return; - const targeEl = this.targetList.find((targetItem) => targetItem.id === ev.target.id.split('_')[2]); + const targeEl = this.targetList.find( + (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''), + ); if (!targeEl) return; // 元素与其所属组同时加入多选列表时,只更新父元素 const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id); @@ -126,6 +128,9 @@ export default class StageMultiDragResize extends EventEmitter { } }); this.multiMoveableHelper?.onDragGroup(params); + }) + .on('dragGroupEnd', () => { + this.update(); }); } @@ -153,4 +158,28 @@ export default class StageMultiDragResize extends EventEmitter { public destroyDragElList(): void { this.dragElList.forEach((dragElItem) => dragElItem?.remove()); } + + /** + * 拖拽完成后将更新的位置信息暴露给上层业务方,业务方可以接收事件进行保存 + * @param isResize 是否进行大小缩放 + */ + private update(isResize = false): void { + if (this.targetList.length === 0) return; + + const { contentWindow } = this.core.renderer; + const doc = contentWindow?.document; + if (!doc) return; + + this.targetList.forEach((targetItem) => { + const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop }; + const left = calcValueByFontsize(doc, offset.left); + const top = calcValueByFontsize(doc, offset.top); + const width = calcValueByFontsize(doc, targetItem.clientWidth); + const height = calcValueByFontsize(doc, targetItem.clientHeight); + this.emit('update', { + el: targetItem, + style: isResize ? { left, top, width, height } : { left, top }, + }); + }); + } }