diff --git a/docs/src/api/stage/core.md b/docs/src/api/stage/core.md index 6ff27e96..b5ed9996 100644 --- a/docs/src/api/stage/core.md +++ b/docs/src/api/stage/core.md @@ -160,7 +160,7 @@ StageDragResize实例 销毁实例 -### setElementFromPoint +### getElementFromPoint - **参数:** diff --git a/packages/editor/src/layouts/sidebar/ComponentListPanel.vue b/packages/editor/src/layouts/sidebar/ComponentListPanel.vue index 9fb372d4..d85eaf8e 100644 --- a/packages/editor/src/layouts/sidebar/ComponentListPanel.vue +++ b/packages/editor/src/layouts/sidebar/ComponentListPanel.vue @@ -41,8 +41,7 @@ import { computed, defineComponent, inject, ref } from 'vue'; import serialize from 'serialize-javascript'; import type StageCore from '@tmagic/stage'; -import { GHOST_EL_ID_PREFIX } from '@tmagic/stage'; -import { addClassName, removeClassNameByClassName } from '@tmagic/utils'; +import { removeClassNameByClassName } from '@tmagic/utils'; import MIcon from '@editor/components/Icon.vue'; import type { ComponentGroup, ComponentItem, Services, StageOptions } from '@editor/type'; @@ -125,19 +124,9 @@ export default defineComponent({ return; } - if (timeout) return; + if (timeout || !stage.value) return; - timeout = globalThis.setTimeout(async () => { - if (!stageOptions || !stage.value) return; - const doc = stage.value.renderer.contentWindow?.document; - const els = stage.value.getElementsFromPoint(e); - for (const el of els) { - if (doc && !el.id.startsWith(GHOST_EL_ID_PREFIX) && (await stageOptions.isContainer(el))) { - addClassName(el, doc, stageOptions?.containerHighlightClassName); - break; - } - } - }, stageOptions?.containerHighlightDuration); + timeout = stage.value.getAddContainerHighlightClassNameTimeout(e); }, }; }, diff --git a/packages/stage/src/StageCore.ts b/packages/stage/src/StageCore.ts index ae20b6c9..8ecf3a7e 100644 --- a/packages/stage/src/StageCore.ts +++ b/packages/stage/src/StageCore.ts @@ -19,6 +19,7 @@ import { EventEmitter } from 'events'; import type { Id } from '@tmagic/schema'; +import { addClassName } from '@tmagic/utils'; import { DEFAULT_ZOOM, GHOST_EL_ID_PREFIX, PAGE_CLASS } from './const'; import StageDragResize from './StageDragResize'; @@ -86,7 +87,7 @@ export default class StageCore extends EventEmitter { this.mask .on('beforeSelect', async (event: MouseEvent) => { this.clearSelectStatus('multiSelect'); - const el = await this.setElementFromPoint(event); + const el = await this.getElementFromPoint(event); if (!el) return; this.select(el, event); }) @@ -98,7 +99,7 @@ export default class StageCore extends EventEmitter { this.emit('changeGuides', data); }) .on('highlight', async (event: MouseEvent) => { - const el = await this.setElementFromPoint(event, 'mousemove'); + const el = await this.getElementFromPoint(event, 'mousemove'); if (!el) return; await this.highlight(el); if (this.highlightedDom === this.selectedDom) { @@ -111,7 +112,7 @@ export default class StageCore extends EventEmitter { this.highlightLayer.clearHighlight(); }) .on('beforeMultiSelect', async (event: MouseEvent) => { - const el = await this.setElementFromPoint(event); + const el = await this.getElementFromPoint(event); if (!el) return; // 多选不可以选中magic-ui-page if (el.className.includes(PAGE_CLASS)) return; @@ -165,7 +166,7 @@ export default class StageCore extends EventEmitter { return doc?.elementsFromPoint(x / zoom, y / zoom) as HTMLElement[]; } - public async setElementFromPoint(event: MouseEvent, type?: String) { + public async getElementFromPoint(event: MouseEvent, type?: String) { const els = this.getElementsFromPoint(event); let stopped = false; const stop = () => (stopped = true); @@ -306,6 +307,27 @@ export default class StageCore extends EventEmitter { this.dr.clearGuides(); } + public async addContainerHighlightClassName(event: MouseEvent, exclude: Element[]) { + const els = this.getElementsFromPoint(event); + const { renderer } = this; + const doc = renderer.contentWindow?.document; + + if (!doc) return; + + for (const el of els) { + if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.isContainer(el)) && !exclude.includes(el)) { + addClassName(el, doc, this.containerHighlightClassName); + break; + } + } + } + + public getAddContainerHighlightClassNameTimeout(event: MouseEvent, exclude: Element[] = []) { + return globalThis.setTimeout(() => { + this.addContainerHighlightClassName(event, exclude); + }, this.containerHighlightDuration); + } + /** * 销毁实例 */ diff --git a/packages/stage/src/StageDragResize.ts b/packages/stage/src/StageDragResize.ts index e7cc91c8..b8ab4581 100644 --- a/packages/stage/src/StageDragResize.ts +++ b/packages/stage/src/StageDragResize.ts @@ -23,7 +23,7 @@ import type { MoveableOptions } from 'moveable'; import Moveable from 'moveable'; import MoveableHelper from 'moveable-helper'; -import { addClassName, removeClassNameByClassName } from '@tmagic/utils'; +import { removeClassNameByClassName } from '@tmagic/utils'; import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const'; import StageCore from './StageCore'; @@ -299,6 +299,7 @@ export default class StageDragResize extends EventEmitter { if (this.mode === Mode.SORTABLE) { this.ghostEl = this.generateGhostEl(this.target); } + frame.top = this.target.offsetTop; frame.left = this.target.offsetLeft; }) @@ -310,20 +311,7 @@ export default class StageDragResize extends EventEmitter { timeout = undefined; } - timeout = globalThis.setTimeout(async () => { - const els = this.core.getElementsFromPoint(e.inputEvent); - for (const el of els) { - if ( - doc && - !el.id.startsWith(GHOST_EL_ID_PREFIX) && - el !== this.target && - (await this.core.isContainer(el)) - ) { - addClassName(el, doc, this.core.containerHighlightClassName); - break; - } - } - }, this.core.containerHighlightDuration); + timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]); this.dragStatus = ActionStatus.ING; @@ -483,6 +471,7 @@ export default class StageDragResize extends EventEmitter { } const ghostEl = el.cloneNode(true) as HTMLElement; + this.setGhostElChildrenId(ghostEl); const { top, left } = getAbsolutePosition(el, getOffset(el)); ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`; ghostEl.style.zIndex = ZIndex.GHOST_EL; @@ -494,6 +483,18 @@ export default class StageDragResize extends EventEmitter { return ghostEl; } + private setGhostElChildrenId(el: Element) { + for (const child of el.children) { + if (child.id) { + child.id = `${GHOST_EL_ID_PREFIX}${child.id}`; + } + + if (child.children.length) { + this.setGhostElChildrenId(child); + } + } + } + private destroyGhostEl(): void { this.ghostEl?.remove(); this.ghostEl = undefined; diff --git a/packages/stage/src/types.ts b/packages/stage/src/types.ts index a73891e7..48a12341 100644 --- a/packages/stage/src/types.ts +++ b/packages/stage/src/types.ts @@ -19,7 +19,7 @@ import { MoveableOptions } from 'moveable'; import Core from '@tmagic/core'; -import type { Id, MApp, MNode } from '@tmagic/schema'; +import type { Id, MApp, MContainer, MNode } from '@tmagic/schema'; import { GuidesType } from './const'; import StageCore from './StageCore'; @@ -99,6 +99,7 @@ export interface SortEventData { export interface UpdateData { config: MNode; + parent?: MContainer; root: MApp; }