From f8125aa1492aceceaef05330f8bfb1e96b280829 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Tue, 28 Nov 2023 16:19:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(stage):=20=E6=94=AF=E6=8C=81=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=AF=B9=E9=BD=90=E5=85=83=E7=B4=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/stage/src/ActionManager.ts | 1 + packages/stage/src/MoveableOptionsManager.ts | 37 +++++++++++++++----- packages/stage/src/StageDragResize.ts | 4 +-- packages/stage/src/StageMultiDragResize.ts | 4 +-- packages/stage/src/types.ts | 1 + playground/src/pages/Editor.vue | 2 +- 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/stage/src/ActionManager.ts b/packages/stage/src/ActionManager.ts index 6721289e1..17f49a003 100644 --- a/packages/stage/src/ActionManager.ts +++ b/packages/stage/src/ActionManager.ts @@ -377,6 +377,7 @@ export default class ActionManager extends EventEmitter { targetEls: this.selectedElList, targetElIds: this.selectedElList?.map((item) => item.id), isMulti, + document: this.getRenderDocument(), }; return options(cfg); } diff --git a/packages/stage/src/MoveableOptionsManager.ts b/packages/stage/src/MoveableOptionsManager.ts index 256c2f4ae..8c6e26ca2 100644 --- a/packages/stage/src/MoveableOptionsManager.ts +++ b/packages/stage/src/MoveableOptionsManager.ts @@ -19,7 +19,7 @@ import EventEmitter from 'events'; import { merge } from 'lodash-es'; -import { MoveableOptions } from 'moveable'; +import type { ElementGuidelineValueOption, MoveableOptions, MoveableRefType } from 'moveable'; import { GuidesType, Mode } from './const'; import MoveableActionsAble from './MoveableActionsAble'; @@ -88,16 +88,19 @@ export default class MoveableOptionsManager extends EventEmitter { /** * 设置有哪些元素要辅助对齐 * @param selectedElList 选中的元素列表,需要排除在对齐元素之外 - * @param allElList 全部元素列表 */ - protected setElementGuidelines(selectedElList: HTMLElement[], allElList: Element[]): void { + protected setElementGuidelines(selectedElList: HTMLElement[]): void { this.elementGuidelines.forEach((node) => { node.remove(); }); this.elementGuidelines = []; + // 设置选中元素的周围元素,用于选中元素跟周围元素对齐辅助 + const elementGuidelines: Array> = + this.getCustomizeOptions()?.elementGuidelines || Array.from(selectedElList[0]?.parentElement?.children || []); + if (this.mode === Mode.ABSOLUTE) { - this.container.append(this.createGuidelineElements(selectedElList, allElList)); + this.container.append(this.createGuidelineElements(selectedElList, elementGuidelines)); } } @@ -224,13 +227,29 @@ export default class MoveableOptionsManager extends EventEmitter { * @param allElList 全部元素列表 * @returns frame 辅助对齐元素集合的页面片 */ - private createGuidelineElements(selectedElList: HTMLElement[], allElList: Element[]): DocumentFragment { + private createGuidelineElements( + selectedElList: HTMLElement[], + allElList: Array>, + ): DocumentFragment { const frame = globalThis.document.createDocumentFragment(); - for (const node of allElList) { - const { width, height } = node.getBoundingClientRect(); - if (this.isInElementList(node, selectedElList)) continue; - const { left, top } = getOffset(node); + for (const element of allElList) { + let node: MoveableRefType = + (element as ElementGuidelineValueOption).element || (element as MoveableRefType); + + if (!node || typeof node === 'string') continue; + + if (typeof node === 'function') { + node = node(); + } + + if (this.isInElementList(node as Element, selectedElList)) continue; + + const { width, height } = (node as Element).getBoundingClientRect(); + + if (!width || !height) continue; + + const { left, top } = getOffset(node as Element); const elementGuideline = globalThis.document.createElement('div'); elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`; this.elementGuidelines.push(elementGuideline); diff --git a/packages/stage/src/StageDragResize.ts b/packages/stage/src/StageDragResize.ts index 70acef51e..ad9a0f394 100644 --- a/packages/stage/src/StageDragResize.ts +++ b/packages/stage/src/StageDragResize.ts @@ -131,9 +131,7 @@ export default class StageDragResize extends MoveableOptionsManager { this.dragResizeHelper.updateShadowEl(el); this.dragResizeHelper.setMode(this.mode); - // 设置选中元素的周围元素,用于选中元素跟周围元素对齐辅助 - const elementGuidelines: Element[] = Array.from(this.target?.parentElement?.children || []); - this.setElementGuidelines([this.target as HTMLElement], elementGuidelines); + this.setElementGuidelines([this.target as HTMLElement]); return this.getOptions(false, { target: this.dragResizeHelper.getShadowEl(), diff --git a/packages/stage/src/StageMultiDragResize.ts b/packages/stage/src/StageMultiDragResize.ts index 5f81e3341..8539225b5 100644 --- a/packages/stage/src/StageMultiDragResize.ts +++ b/packages/stage/src/StageMultiDragResize.ts @@ -79,9 +79,7 @@ export default class StageMultiDragResize extends MoveableOptionsManager { this.dragResizeHelper.updateGroup(els); - // 设置周围元素,用于选中元素跟周围元素的对齐辅助 - const elementGuidelines: Element[] = Array.from(this.targetList[0].parentElement?.children || []); - this.setElementGuidelines(this.targetList, elementGuidelines); + this.setElementGuidelines(this.targetList); this.moveableForMulti?.destroy(); this.dragResizeHelper.clear(); diff --git a/packages/stage/src/types.ts b/packages/stage/src/types.ts index 39e6fa946..2d7706ccb 100644 --- a/packages/stage/src/types.ts +++ b/packages/stage/src/types.ts @@ -101,6 +101,7 @@ export interface CustomizeMoveableOptionsCallbackConfig { targetEls?: HTMLElement[]; targetElIds?: string[]; isMulti: boolean; + document?: Document; } export interface StageRenderConfig { diff --git a/playground/src/pages/Editor.vue b/playground/src/pages/Editor.vue index 2a2ab5673..7a9719ff5 100644 --- a/playground/src/pages/Editor.vue +++ b/playground/src/pages/Editor.vue @@ -52,7 +52,7 @@ import { TMagicDialog, tMagicMessage, tMagicMessageBox } from '@tmagic/design'; import { DatasourceTypeOption, editorService, MenuBarData, MoveableOptions, TMagicEditor } from '@tmagic/editor'; import type { MContainer, MNode } from '@tmagic/schema'; import { NodeType } from '@tmagic/schema'; -import { CustomizeMoveableOptionsCallbackConfig } from '@tmagic/stage'; +import type { CustomizeMoveableOptionsCallbackConfig } from '@tmagic/stage'; import { asyncLoadJs } from '@tmagic/utils'; import DeviceGroup from '../components/DeviceGroup.vue';