mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-04-06 03:57:56 +08:00
feat: 支持配置updateDragEl方法来调制选中框
This commit is contained in:
parent
10577aea68
commit
154860c66c
@ -12,13 +12,7 @@
|
||||
|
||||
<template #workspace :editorService="editorService">
|
||||
<slot name="workspace">
|
||||
<workspace
|
||||
:runtime-url="runtimeUrl"
|
||||
:auto-scroll-into-view="autoScrollIntoView"
|
||||
:render="render"
|
||||
:moveable-options="moveableOptions"
|
||||
:can-select="canSelect"
|
||||
>
|
||||
<workspace>
|
||||
<template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
|
||||
<template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
|
||||
<template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
|
||||
@ -37,7 +31,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onUnmounted, PropType, provide, toRaw, watch } from 'vue';
|
||||
import { defineComponent, onUnmounted, PropType, provide, reactive, toRaw, watch } from 'vue';
|
||||
|
||||
import { EventOption } from '@tmagic/core';
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
@ -136,6 +130,9 @@ export default defineComponent({
|
||||
/** 画布中组件选中框的移动范围 */
|
||||
moveableOptions: {
|
||||
type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
|
||||
default: () => (core?: StageCore) => ({
|
||||
container: core?.renderer?.contentWindow?.document.getElementById('app'),
|
||||
}),
|
||||
},
|
||||
|
||||
/** 编辑器初始化时默认选中的组件ID */
|
||||
@ -145,6 +142,7 @@ export default defineComponent({
|
||||
|
||||
canSelect: {
|
||||
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
||||
default: (el: HTMLElement) => Boolean(el.id),
|
||||
},
|
||||
|
||||
stageRect: {
|
||||
@ -155,6 +153,10 @@ export default defineComponent({
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
updateDragEl: {
|
||||
type: Function as PropType<(el: HTMLDivElement, target: HTMLElement) => void>,
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['props-panel-mounted', 'update:modelValue'],
|
||||
@ -249,6 +251,17 @@ export default defineComponent({
|
||||
|
||||
provide('layerContentMenu', props.layerContentMenu);
|
||||
provide('stageContentMenu', props.stageContentMenu);
|
||||
provide(
|
||||
'stageOptions',
|
||||
reactive({
|
||||
runtimeUrl: props.runtimeUrl,
|
||||
autoScrollIntoView: props.autoScrollIntoView,
|
||||
render: props.render,
|
||||
moveableOptions: props.moveableOptions,
|
||||
canSelect: props.canSelect,
|
||||
updateDragEl: props.updateDragEl,
|
||||
}),
|
||||
);
|
||||
|
||||
return services;
|
||||
},
|
||||
|
@ -28,7 +28,6 @@ import {
|
||||
markRaw,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
PropType,
|
||||
ref,
|
||||
toRaw,
|
||||
watch,
|
||||
@ -37,11 +36,11 @@ import {
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
import type { MApp, MNode, MPage } from '@tmagic/schema';
|
||||
import type { MoveableOptions, Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
|
||||
import type { Runtime, SortEventData, UpdateEventData } from '@tmagic/stage';
|
||||
import StageCore from '@tmagic/stage';
|
||||
|
||||
import ScrollViewer from '@editor/components/ScrollViewer.vue';
|
||||
import { Layout, Services, StageRect } from '@editor/type';
|
||||
import { Layout, Services, StageOptions, StageRect } from '@editor/type';
|
||||
|
||||
import ViewerMenu from './ViewerMenu.vue';
|
||||
|
||||
@ -53,29 +52,9 @@ export default defineComponent({
|
||||
ScrollViewer,
|
||||
},
|
||||
|
||||
props: {
|
||||
render: {
|
||||
type: Function as PropType<() => HTMLDivElement>,
|
||||
},
|
||||
|
||||
runtimeUrl: String,
|
||||
autoScrollIntoView: Boolean,
|
||||
|
||||
canSelect: {
|
||||
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
||||
default: (el: HTMLElement) => Boolean(el.id),
|
||||
},
|
||||
|
||||
moveableOptions: {
|
||||
type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
|
||||
default: () => (core?: StageCore) => ({
|
||||
container: core?.renderer?.contentWindow?.document.getElementById('app'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
setup() {
|
||||
const services = inject<Services>('services');
|
||||
const stageOptions = inject<StageOptions>('stageOptions');
|
||||
|
||||
const stageWrap = ref<InstanceType<typeof ScrollViewer>>();
|
||||
const stageContainer = ref<HTMLDivElement>();
|
||||
@ -95,15 +74,15 @@ export default defineComponent({
|
||||
if (stage) return;
|
||||
|
||||
if (!stageContainer.value) return;
|
||||
if (!(props.runtimeUrl || props.render) || !root.value) return;
|
||||
if (!(stageOptions?.runtimeUrl || stageOptions?.render) || !root.value) return;
|
||||
|
||||
stage = new StageCore({
|
||||
render: props.render,
|
||||
runtimeUrl: props.runtimeUrl,
|
||||
render: stageOptions.render,
|
||||
runtimeUrl: stageOptions.runtimeUrl,
|
||||
zoom: zoom.value,
|
||||
autoScrollIntoView: props.autoScrollIntoView,
|
||||
autoScrollIntoView: stageOptions.autoScrollIntoView,
|
||||
canSelect: (el, event, stop) => {
|
||||
const elCanSelect = props.canSelect(el);
|
||||
const elCanSelect = stageOptions.canSelect(el);
|
||||
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
||||
if (uiSelectMode.value && elCanSelect && event.type === 'mousedown') {
|
||||
document.dispatchEvent(new CustomEvent('ui-select', { detail: el }));
|
||||
@ -112,7 +91,8 @@ export default defineComponent({
|
||||
|
||||
return elCanSelect;
|
||||
},
|
||||
moveableOptions: props.moveableOptions,
|
||||
moveableOptions: stageOptions.moveableOptions,
|
||||
updateDragEl: stageOptions.updateDragEl,
|
||||
});
|
||||
|
||||
services?.editorService.set('stage', markRaw(stage));
|
||||
|
@ -1,13 +1,6 @@
|
||||
<template>
|
||||
<div class="m-editor-workspace" tabindex="1" ref="workspace">
|
||||
<magic-stage
|
||||
:key="page?.id"
|
||||
:runtime-url="runtimeUrl"
|
||||
:auto-scroll-into-view="autoScrollIntoView"
|
||||
:render="render"
|
||||
:moveable-options="moveableOptions"
|
||||
:can-select="canSelect"
|
||||
></magic-stage>
|
||||
<magic-stage :key="page?.id"></magic-stage>
|
||||
|
||||
<slot name="workspace-content"></slot>
|
||||
|
||||
@ -19,12 +12,10 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, inject, onMounted, onUnmounted, PropType, ref } from 'vue';
|
||||
import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
|
||||
import KeyController from 'keycon';
|
||||
|
||||
import type { MNode, MPage } from '@tmagic/schema';
|
||||
import type { MoveableOptions } from '@tmagic/stage';
|
||||
import StageCore from '@tmagic/stage';
|
||||
import { isPage } from '@tmagic/utils';
|
||||
|
||||
import type { Services } from '@editor/type';
|
||||
@ -40,23 +31,6 @@ export default defineComponent({
|
||||
MagicStage,
|
||||
},
|
||||
|
||||
props: {
|
||||
runtimeUrl: String,
|
||||
autoScrollIntoView: Boolean,
|
||||
|
||||
render: {
|
||||
type: Function as PropType<() => HTMLDivElement>,
|
||||
},
|
||||
|
||||
moveableOptions: {
|
||||
type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
|
||||
},
|
||||
|
||||
canSelect: {
|
||||
type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
|
||||
},
|
||||
},
|
||||
|
||||
setup() {
|
||||
const services = inject<Services>('services');
|
||||
const workspace = ref<HTMLDivElement>();
|
||||
|
@ -21,6 +21,7 @@ import type { Component } from 'vue';
|
||||
import type { FormConfig } from '@tmagic/form';
|
||||
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
||||
import type StageCore from '@tmagic/stage';
|
||||
import type { MoveableOptions } from '@tmagic/stage';
|
||||
|
||||
import type { ComponentListService } from '@editor/services/componentList';
|
||||
import type { EditorService } from '@editor/services/editor';
|
||||
@ -45,6 +46,15 @@ export interface Services {
|
||||
uiService: UiService;
|
||||
}
|
||||
|
||||
export interface StageOptions {
|
||||
runtimeUrl: string;
|
||||
autoScrollIntoView: boolean;
|
||||
render: () => HTMLDivElement;
|
||||
moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
|
||||
canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
|
||||
updateDragEl: (el: HTMLDivElement) => void;
|
||||
}
|
||||
|
||||
export interface StoreState {
|
||||
root: MApp | null;
|
||||
page: MPage | null;
|
||||
|
@ -48,7 +48,7 @@ export default class StageDragResize extends EventEmitter {
|
||||
/** 目标节点 */
|
||||
public target?: HTMLElement;
|
||||
/** 目标节点在蒙层中的占位节点 */
|
||||
public dragEl: HTMLElement;
|
||||
public dragEl: HTMLDivElement;
|
||||
/** Moveable拖拽类实例 */
|
||||
public moveable?: Moveable;
|
||||
/** 水平参考线 */
|
||||
@ -87,10 +87,9 @@ export default class StageDragResize extends EventEmitter {
|
||||
const oldTarget = this.target;
|
||||
this.target = el;
|
||||
|
||||
this.init(el);
|
||||
|
||||
// 从不能拖动到能拖动的节点之间切换,要重新创建moveable,不然dragStart不生效
|
||||
if (!this.moveable || this.target !== oldTarget) {
|
||||
this.init(el);
|
||||
this.moveableHelper = MoveableHelper.create({
|
||||
useBeforeRender: true,
|
||||
useRender: false,
|
||||
@ -430,6 +429,10 @@ export default class StageDragResize extends EventEmitter {
|
||||
`;
|
||||
|
||||
this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
|
||||
|
||||
if (typeof this.core.config.updateDragEl === 'function') {
|
||||
this.core.config.updateDragEl(this.dragEl, el);
|
||||
}
|
||||
}
|
||||
|
||||
private destroyDragEl(): void {
|
||||
|
@ -41,6 +41,7 @@ export default class StageHighlight extends EventEmitter {
|
||||
parent: this.core.mask.content,
|
||||
mask: this.core.mask,
|
||||
dr: this.core.dr,
|
||||
core: this.core,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { Mode } from './const';
|
||||
import StageCore from './StageCore';
|
||||
import StageDragResize from './StageDragResize';
|
||||
import StageMask from './StageMask';
|
||||
import type { Offset, TargetCalibrateConfig } from './types';
|
||||
@ -32,7 +33,8 @@ export default class TargetCalibrate extends EventEmitter {
|
||||
public parent: HTMLElement;
|
||||
public mask: StageMask;
|
||||
public dr: StageDragResize;
|
||||
public operationEl: HTMLElement;
|
||||
public core: StageCore;
|
||||
public operationEl: HTMLDivElement;
|
||||
|
||||
constructor(config: TargetCalibrateConfig) {
|
||||
super();
|
||||
@ -40,6 +42,7 @@ export default class TargetCalibrate extends EventEmitter {
|
||||
this.parent = config.parent;
|
||||
this.mask = config.mask;
|
||||
this.dr = config.dr;
|
||||
this.core = config.core;
|
||||
|
||||
this.operationEl = globalThis.document.createElement('div');
|
||||
this.parent.append(this.operationEl);
|
||||
@ -58,6 +61,11 @@ export default class TargetCalibrate extends EventEmitter {
|
||||
`;
|
||||
|
||||
this.operationEl.id = `${prefix}${el.id}`;
|
||||
|
||||
if (typeof this.core.config.updateDragEl === 'function') {
|
||||
this.core.config.updateDragEl(this.operationEl, el);
|
||||
}
|
||||
|
||||
return this.operationEl;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ export type StageCoreConfig = {
|
||||
runtimeUrl?: string;
|
||||
render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
|
||||
autoScrollIntoView?: boolean;
|
||||
updateDragEl?: (el: HTMLDivElement, target: HTMLElement) => void;
|
||||
};
|
||||
|
||||
export interface StageRenderConfig {
|
||||
@ -133,4 +134,5 @@ export interface TargetCalibrateConfig {
|
||||
parent: HTMLElement;
|
||||
mask: StageMask;
|
||||
dr: StageDragResize;
|
||||
core: StageCore;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user