@tmagic/stage 1.2.0-beta.9 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -1
- package/dist/{tmagic-stage.mjs → tmagic-stage.js} +1395 -1062
- package/dist/tmagic-stage.js.map +1 -0
- package/dist/{tmagic-stage.umd.js → tmagic-stage.umd.cjs} +1393 -1060
- package/dist/tmagic-stage.umd.cjs.map +1 -0
- package/package.json +9 -8
- package/src/ActionManager.ts +535 -0
- package/src/DragResizeHelper.ts +338 -0
- package/src/MoveableOptionsManager.ts +249 -0
- package/src/MoveableSelectParentAble.ts +3 -5
- package/src/Rule.ts +4 -4
- package/src/StageCore.ts +203 -275
- package/src/StageDragResize.ts +86 -348
- package/src/StageHighlight.ts +17 -16
- package/src/StageMask.ts +19 -102
- package/src/StageMultiDragResize.ts +97 -198
- package/src/StageRender.ts +85 -10
- package/src/TargetShadow.ts +120 -0
- package/src/const.ts +1 -1
- package/src/types.ts +99 -19
- package/src/util.ts +18 -11
- package/types/ActionManager.d.ts +141 -0
- package/types/DragResizeHelper.d.ts +70 -0
- package/types/MoveableOptionsManager.d.ts +86 -0
- package/types/MoveableSelectParentAble.d.ts +1 -2
- package/types/StageCore.d.ts +58 -41
- package/types/StageDragResize.d.ts +12 -40
- package/types/StageHighlight.d.ts +3 -4
- package/types/StageMask.d.ts +0 -21
- package/types/StageMultiDragResize.d.ts +8 -24
- package/types/StageRender.d.ts +23 -4
- package/types/TargetShadow.d.ts +22 -0
- package/types/const.d.ts +1 -1
- package/types/types.d.ts +87 -18
- package/types/util.d.ts +8 -8
- package/dist/tmagic-stage.mjs.map +0 -1
- package/dist/tmagic-stage.umd.js.map +0 -1
- package/src/TargetCalibrate.ts +0 -119
- package/types/TargetCalibrate.d.ts +0 -20
package/src/StageCore.ts
CHANGED
|
@@ -18,303 +18,149 @@
|
|
|
18
18
|
|
|
19
19
|
import { EventEmitter } from 'events';
|
|
20
20
|
|
|
21
|
-
import
|
|
22
|
-
import { addClassName } from '@tmagic/utils';
|
|
21
|
+
import { Id } from '@tmagic/schema';
|
|
23
22
|
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
import StageHighlight from './StageHighlight';
|
|
23
|
+
import ActionManager from './ActionManager';
|
|
24
|
+
import { DEFAULT_ZOOM } from './const';
|
|
27
25
|
import StageMask from './StageMask';
|
|
28
|
-
import StageMultiDragResize from './StageMultiDragResize';
|
|
29
26
|
import StageRender from './StageRender';
|
|
30
27
|
import {
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
ActionManagerConfig,
|
|
29
|
+
CustomizeRender,
|
|
33
30
|
GuidesEventData,
|
|
34
|
-
|
|
31
|
+
Point,
|
|
35
32
|
RemoveData,
|
|
36
33
|
Runtime,
|
|
37
|
-
SortEventData,
|
|
38
34
|
StageCoreConfig,
|
|
39
|
-
StageDragStatus,
|
|
40
35
|
UpdateData,
|
|
41
36
|
UpdateEventData,
|
|
42
37
|
} from './types';
|
|
43
|
-
import { addSelectedClassName, removeSelectedClassName } from './util';
|
|
44
38
|
|
|
39
|
+
/**
|
|
40
|
+
* 负责管理画布,管理renderer、mask、actionManager三个核心类,并负责统一对外通信,包括提供接口和抛事件
|
|
41
|
+
*/
|
|
45
42
|
export default class StageCore extends EventEmitter {
|
|
46
43
|
public container?: HTMLDivElement;
|
|
47
|
-
// 当前选中的节点
|
|
48
|
-
public selectedDom: HTMLElement | undefined;
|
|
49
|
-
// 多选选中的节点组
|
|
50
|
-
public selectedDomList: HTMLElement[] = [];
|
|
51
|
-
public highlightedDom: Element | undefined;
|
|
52
44
|
public renderer: StageRender;
|
|
53
45
|
public mask: StageMask;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
public highlightLayer: StageHighlight;
|
|
57
|
-
public config: StageCoreConfig;
|
|
58
|
-
public zoom = DEFAULT_ZOOM;
|
|
59
|
-
public containerHighlightClassName: string;
|
|
60
|
-
public containerHighlightDuration: number;
|
|
61
|
-
public containerHighlightType?: ContainerHighlightType;
|
|
62
|
-
public isContainer: IsContainer;
|
|
63
|
-
|
|
64
|
-
private canSelect: CanSelect;
|
|
46
|
+
|
|
47
|
+
private actionManager: ActionManager;
|
|
65
48
|
private pageResizeObserver: ResizeObserver | null = null;
|
|
49
|
+
private autoScrollIntoView: boolean | undefined;
|
|
50
|
+
private customizedRender?: CustomizeRender;
|
|
66
51
|
|
|
67
52
|
constructor(config: StageCoreConfig) {
|
|
68
53
|
super();
|
|
69
54
|
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
this.setZoom(config.zoom);
|
|
73
|
-
this.canSelect = config.canSelect || ((el: HTMLElement) => !!el.id);
|
|
74
|
-
this.isContainer = config.isContainer;
|
|
75
|
-
this.containerHighlightClassName = config.containerHighlightClassName || CONTAINER_HIGHLIGHT_CLASS;
|
|
76
|
-
this.containerHighlightDuration = config.containerHighlightDuration || 800;
|
|
77
|
-
this.containerHighlightType = config.containerHighlightType;
|
|
78
|
-
|
|
79
|
-
this.renderer = new StageRender({ runtimeUrl: config.runtimeUrl, render: this.render.bind(this) });
|
|
80
|
-
this.mask = new StageMask();
|
|
81
|
-
this.dr = new StageDragResize({ core: this, container: this.mask.content, mask: this.mask });
|
|
82
|
-
this.multiDr = new StageMultiDragResize({ core: this, container: this.mask.content, mask: this.mask });
|
|
83
|
-
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
|
|
84
|
-
|
|
85
|
-
this.renderer.on('runtime-ready', (runtime: Runtime) => {
|
|
86
|
-
this.emit('runtime-ready', runtime);
|
|
87
|
-
});
|
|
88
|
-
this.renderer.on('page-el-update', (el: HTMLElement) => {
|
|
89
|
-
this.mask?.observe(el);
|
|
90
|
-
this.observePageResize(el);
|
|
91
|
-
});
|
|
55
|
+
this.autoScrollIntoView = config.autoScrollIntoView;
|
|
56
|
+
this.customizedRender = config.render;
|
|
92
57
|
|
|
93
|
-
this.
|
|
94
|
-
.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
})
|
|
100
|
-
.on('select', () => {
|
|
101
|
-
this.emit('select', this.selectedDom);
|
|
102
|
-
})
|
|
103
|
-
.on('changeGuides', (data: GuidesEventData) => {
|
|
104
|
-
this.dr.setGuidelines(data.type, data.guides);
|
|
105
|
-
this.emit('changeGuides', data);
|
|
106
|
-
})
|
|
107
|
-
.on('highlight', async (event: MouseEvent) => {
|
|
108
|
-
const el = await this.getElementFromPoint(event);
|
|
109
|
-
if (!el) return;
|
|
110
|
-
// 如果多选组件处于拖拽状态时不进行组件高亮
|
|
111
|
-
if (this.multiDr.dragStatus === StageDragStatus.ING) return;
|
|
112
|
-
await this.highlight(el);
|
|
113
|
-
if (this.highlightedDom === this.selectedDom) {
|
|
114
|
-
this.highlightLayer.clearHighlight();
|
|
115
|
-
return;
|
|
58
|
+
this.renderer = new StageRender({
|
|
59
|
+
runtimeUrl: config.runtimeUrl,
|
|
60
|
+
zoom: config.zoom,
|
|
61
|
+
customizedRender: async (): Promise<HTMLElement | null> => {
|
|
62
|
+
if (this?.customizedRender) {
|
|
63
|
+
return await this.customizedRender(this);
|
|
116
64
|
}
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
.on('beforeMultiSelect', async (event: MouseEvent) => {
|
|
123
|
-
const el = await this.getElementFromPoint(event);
|
|
124
|
-
if (!el) return;
|
|
125
|
-
// 如果已有单选选中元素,不是magic-ui-page就可以加入多选列表
|
|
126
|
-
if (this.selectedDom && !this.selectedDom.className.includes(PAGE_CLASS)) {
|
|
127
|
-
this.selectedDomList.push(this.selectedDom as HTMLElement);
|
|
128
|
-
this.selectedDom = undefined;
|
|
129
|
-
}
|
|
130
|
-
// 判断元素是否已在多选列表
|
|
131
|
-
const existIndex = this.selectedDomList.findIndex((selectedDom) => selectedDom.id === el.id);
|
|
132
|
-
if (existIndex !== -1) {
|
|
133
|
-
// 再次点击取消选中
|
|
134
|
-
this.selectedDomList.splice(existIndex, 1);
|
|
135
|
-
} else {
|
|
136
|
-
this.selectedDomList.push(el);
|
|
137
|
-
}
|
|
138
|
-
this.multiSelect(this.selectedDomList);
|
|
139
|
-
this.emit('multiSelect', this.selectedDomList);
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// 要先触发select,在触发update
|
|
143
|
-
this.dr
|
|
144
|
-
.on('update', (data: UpdateEventData) => {
|
|
145
|
-
setTimeout(() => this.emit('update', data));
|
|
146
|
-
})
|
|
147
|
-
.on('sort', (data: UpdateEventData) => {
|
|
148
|
-
setTimeout(() => this.emit('sort', data));
|
|
149
|
-
})
|
|
150
|
-
.on('select-parent', () => {
|
|
151
|
-
this.emit('select-parent');
|
|
152
|
-
});
|
|
65
|
+
return null;
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
this.mask = new StageMask();
|
|
69
|
+
this.actionManager = new ActionManager(this.getActionManagerConfig(config));
|
|
153
70
|
|
|
154
|
-
this.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
})
|
|
158
|
-
.on('select', async (id: Id) => {
|
|
159
|
-
const el = await this.getTargetElement(id);
|
|
160
|
-
this.select(el); // 选中
|
|
161
|
-
setTimeout(() => this.emit('select', el)); // set node
|
|
162
|
-
});
|
|
71
|
+
this.initRenderEvent();
|
|
72
|
+
this.initActionEvent();
|
|
73
|
+
this.initMaskEvent();
|
|
163
74
|
}
|
|
164
75
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
76
|
+
/**
|
|
77
|
+
* 单选选中元素
|
|
78
|
+
* @param idOrEl 选中的id或者元素
|
|
79
|
+
*/
|
|
80
|
+
public async select(idOrEl: Id | HTMLElement, event?: MouseEvent): Promise<void> {
|
|
81
|
+
const el = this.renderer.getTargetElement(idOrEl);
|
|
82
|
+
if (el === this.actionManager.getSelectedEl()) return;
|
|
170
83
|
|
|
171
|
-
|
|
172
|
-
const rect = renderer.iframe.getClientRects()[0];
|
|
173
|
-
if (rect) {
|
|
174
|
-
x = x - rect.left;
|
|
175
|
-
y = y - rect.top;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
84
|
+
await this.renderer.select([el]);
|
|
178
85
|
|
|
179
|
-
|
|
180
|
-
}
|
|
86
|
+
this.mask.setLayout(el);
|
|
181
87
|
|
|
182
|
-
|
|
183
|
-
const els = this.getElementsFromPoint(event);
|
|
184
|
-
let stopped = false;
|
|
185
|
-
const stop = () => (stopped = true);
|
|
186
|
-
for (const el of els) {
|
|
187
|
-
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.isElCanSelect(el, event, stop))) {
|
|
188
|
-
if (stopped) break;
|
|
189
|
-
return el;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
88
|
+
this.actionManager.select(el, event);
|
|
193
89
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const canSelectByProp = await this.canSelect(el, event, stop);
|
|
197
|
-
if (!canSelectByProp) return false;
|
|
198
|
-
// 多选规则
|
|
199
|
-
if (this.mask.isMultiSelectStatus) {
|
|
200
|
-
return this.multiDr.canSelect(el, stop);
|
|
90
|
+
if (this.autoScrollIntoView || el.dataset.autoScrollIntoView) {
|
|
91
|
+
this.mask.observerIntersection(el);
|
|
201
92
|
}
|
|
202
|
-
return true;
|
|
203
93
|
}
|
|
204
94
|
|
|
205
95
|
/**
|
|
206
|
-
*
|
|
207
|
-
* @param
|
|
96
|
+
* 多选选中多个元素
|
|
97
|
+
* @param idOrElList 选中元素的id或元素列表
|
|
208
98
|
*/
|
|
209
|
-
public async
|
|
210
|
-
this.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (el === this.selectedDom) return;
|
|
214
|
-
|
|
215
|
-
const runtime = await this.renderer.getRuntime();
|
|
99
|
+
public async multiSelect(idOrElList: HTMLElement[] | Id[]): Promise<void> {
|
|
100
|
+
const els = idOrElList.map((idOrEl) => this.renderer.getTargetElement(idOrEl));
|
|
101
|
+
if (els.length === 0) return;
|
|
216
102
|
|
|
217
|
-
|
|
103
|
+
const lastEl = els[els.length - 1];
|
|
104
|
+
// 是否减少了组件选择
|
|
105
|
+
const isReduceSelect = els.length < this.actionManager.getSelectedElList().length;
|
|
106
|
+
await this.renderer.select(els);
|
|
218
107
|
|
|
219
|
-
|
|
220
|
-
await runtime.beforeSelect(el);
|
|
221
|
-
}
|
|
108
|
+
this.mask.setLayout(lastEl);
|
|
222
109
|
|
|
223
|
-
this.
|
|
224
|
-
this.dr.select(el, event);
|
|
110
|
+
this.actionManager.multiSelect(idOrElList);
|
|
225
111
|
|
|
226
|
-
if (this.
|
|
227
|
-
this.mask.observerIntersection(
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
this.selectedDom = el;
|
|
231
|
-
|
|
232
|
-
const doc = this.renderer.getDocument();
|
|
233
|
-
if (doc) {
|
|
234
|
-
removeSelectedClassName(doc);
|
|
235
|
-
if (this.selectedDom) {
|
|
236
|
-
addSelectedClassName(this.selectedDom, doc);
|
|
237
|
-
}
|
|
112
|
+
if ((this.autoScrollIntoView || lastEl.dataset.autoScrollIntoView) && !isReduceSelect) {
|
|
113
|
+
this.mask.observerIntersection(lastEl);
|
|
238
114
|
}
|
|
239
115
|
}
|
|
240
116
|
|
|
241
117
|
/**
|
|
242
|
-
*
|
|
243
|
-
* @param
|
|
118
|
+
* 高亮选中元素
|
|
119
|
+
* @param el 要高亮的元素
|
|
244
120
|
*/
|
|
245
|
-
public
|
|
246
|
-
this.
|
|
247
|
-
this.selectedDomList = await Promise.all(idOrElList.map(async (idOrEl) => await this.getTargetElement(idOrEl)));
|
|
248
|
-
this.multiDr.multiSelect(this.selectedDomList);
|
|
121
|
+
public highlight(idOrEl: Id | HTMLElement): void {
|
|
122
|
+
this.actionManager.highlight(idOrEl);
|
|
249
123
|
}
|
|
250
124
|
|
|
251
125
|
/**
|
|
252
|
-
*
|
|
253
|
-
* @param data
|
|
126
|
+
* 更新组件
|
|
127
|
+
* @param data 更新组件的数据
|
|
254
128
|
*/
|
|
255
|
-
public update(data: UpdateData): Promise<void> {
|
|
129
|
+
public async update(data: UpdateData): Promise<void> {
|
|
256
130
|
const { config } = data;
|
|
257
131
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
270
|
-
}, 0);
|
|
132
|
+
await this.renderer.update(data);
|
|
133
|
+
// 通过setTimeout等画布中组件完成渲染更新
|
|
134
|
+
setTimeout(() => {
|
|
135
|
+
const el = this.renderer.getTargetElement(`${config.id}`);
|
|
136
|
+
if (el && this.actionManager.isSelectedEl(el)) {
|
|
137
|
+
// 更新了组件的布局,需要重新设置mask是否可以滚动
|
|
138
|
+
this.mask.setLayout(el);
|
|
139
|
+
// 组件有更新,需要set
|
|
140
|
+
this.actionManager.setSelectedEl(el);
|
|
141
|
+
this.actionManager.updateMoveable(el);
|
|
142
|
+
}
|
|
271
143
|
});
|
|
272
144
|
}
|
|
273
145
|
|
|
274
146
|
/**
|
|
275
|
-
*
|
|
276
|
-
* @param
|
|
147
|
+
* 往画布增加一个组件
|
|
148
|
+
* @param data 组件信息数据
|
|
277
149
|
*/
|
|
278
|
-
public async
|
|
279
|
-
|
|
280
|
-
try {
|
|
281
|
-
el = await this.getTargetElement(idOrEl);
|
|
282
|
-
} catch (error) {
|
|
283
|
-
this.highlightLayer.clearHighlight();
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
if (el === this.highlightedDom || !el) return;
|
|
287
|
-
this.highlightLayer.highlight(el);
|
|
288
|
-
this.highlightedDom = el;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
public sortNode(data: SortEventData): Promise<void> {
|
|
292
|
-
return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
|
|
150
|
+
public async add(data: UpdateData): Promise<void> {
|
|
151
|
+
return await this.renderer.add(data);
|
|
293
152
|
}
|
|
294
153
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
public remove(data: RemoveData): Promise<void> {
|
|
300
|
-
return this.renderer
|
|
154
|
+
/**
|
|
155
|
+
* 从画布删除一个组件
|
|
156
|
+
* @param data 组件信息数据
|
|
157
|
+
*/
|
|
158
|
+
public async remove(data: RemoveData): Promise<void> {
|
|
159
|
+
return await this.renderer.remove(data);
|
|
301
160
|
}
|
|
302
161
|
|
|
303
162
|
public setZoom(zoom: number = DEFAULT_ZOOM): void {
|
|
304
|
-
this.zoom
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* 用于在切换选择模式时清除上一次的状态
|
|
309
|
-
* @param selectType 需要清理的选择模式 多选:multiSelect,单选:select
|
|
310
|
-
*/
|
|
311
|
-
public clearSelectStatus(selectType: String) {
|
|
312
|
-
if (selectType === 'multiSelect') {
|
|
313
|
-
this.multiDr.clearSelectStatus();
|
|
314
|
-
this.selectedDomList = [];
|
|
315
|
-
} else {
|
|
316
|
-
this.dr.clearSelectStatus();
|
|
317
|
-
}
|
|
163
|
+
this.renderer.setZoom(zoom);
|
|
318
164
|
}
|
|
319
165
|
|
|
320
166
|
/**
|
|
@@ -336,40 +182,36 @@ export default class StageCore extends EventEmitter {
|
|
|
336
182
|
*/
|
|
337
183
|
public clearGuides() {
|
|
338
184
|
this.mask.clearGuides();
|
|
339
|
-
this.
|
|
185
|
+
this.actionManager.clearGuides();
|
|
340
186
|
}
|
|
341
187
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (!doc) return;
|
|
348
|
-
|
|
349
|
-
for (const el of els) {
|
|
350
|
-
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && (await this.isContainer(el)) && !exclude.includes(el)) {
|
|
351
|
-
addClassName(el, doc, this.containerHighlightClassName);
|
|
352
|
-
break;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
188
|
+
/**
|
|
189
|
+
* @deprecated 废弃接口,建议用delayedMarkContainer代替
|
|
190
|
+
*/
|
|
191
|
+
public getAddContainerHighlightClassNameTimeout(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout {
|
|
192
|
+
return this.delayedMarkContainer(event, excludeElList);
|
|
355
193
|
}
|
|
356
194
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
195
|
+
/**
|
|
196
|
+
* 鼠标拖拽着元素,在容器上方悬停,延迟一段时间后,对容器进行标记,如果悬停时间够长将标记成功,悬停时间短,调用方通过返回的timeoutId取消标记
|
|
197
|
+
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
|
198
|
+
* @param event 鼠标事件
|
|
199
|
+
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
200
|
+
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
201
|
+
*/
|
|
202
|
+
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout {
|
|
203
|
+
return this.actionManager.delayedMarkContainer(event, excludeElList);
|
|
361
204
|
}
|
|
362
205
|
|
|
363
206
|
/**
|
|
364
207
|
* 销毁实例
|
|
365
208
|
*/
|
|
366
209
|
public destroy(): void {
|
|
367
|
-
const { mask, renderer,
|
|
210
|
+
const { mask, renderer, actionManager, pageResizeObserver } = this;
|
|
368
211
|
|
|
369
212
|
renderer.destroy();
|
|
370
213
|
mask.destroy();
|
|
371
|
-
|
|
372
|
-
highlightLayer.destroy();
|
|
214
|
+
actionManager.destroy();
|
|
373
215
|
pageResizeObserver?.disconnect();
|
|
374
216
|
|
|
375
217
|
this.removeAllListeners();
|
|
@@ -384,32 +226,118 @@ export default class StageCore extends EventEmitter {
|
|
|
384
226
|
if (typeof ResizeObserver !== 'undefined') {
|
|
385
227
|
this.pageResizeObserver = new ResizeObserver((entries) => {
|
|
386
228
|
this.mask.pageResize(entries);
|
|
387
|
-
|
|
388
|
-
if (this.dr.moveable) {
|
|
389
|
-
this.dr.updateMoveable();
|
|
390
|
-
}
|
|
229
|
+
this.actionManager.updateMoveable();
|
|
391
230
|
});
|
|
392
231
|
|
|
393
232
|
this.pageResizeObserver.observe(page);
|
|
394
233
|
}
|
|
395
234
|
}
|
|
396
235
|
|
|
236
|
+
private getActionManagerConfig(config: StageCoreConfig): ActionManagerConfig {
|
|
237
|
+
const actionManagerConfig: ActionManagerConfig = {
|
|
238
|
+
containerHighlightClassName: config.containerHighlightClassName,
|
|
239
|
+
containerHighlightDuration: config.containerHighlightDuration,
|
|
240
|
+
containerHighlightType: config.containerHighlightType,
|
|
241
|
+
moveableOptions: config.moveableOptions,
|
|
242
|
+
multiMoveableOptions: config.multiMoveableOptions,
|
|
243
|
+
container: this.mask.content,
|
|
244
|
+
disabledDragStart: config.disabledDragStart,
|
|
245
|
+
canSelect: config.canSelect,
|
|
246
|
+
isContainer: config.isContainer,
|
|
247
|
+
updateDragEl: config.updateDragEl,
|
|
248
|
+
getRootContainer: () => this.container,
|
|
249
|
+
getRenderDocument: () => this.renderer.getDocument(),
|
|
250
|
+
getTargetElement: (idOrEl: Id | HTMLElement) => this.renderer.getTargetElement(idOrEl),
|
|
251
|
+
getElementsFromPoint: (point: Point) => this.renderer.getElementsFromPoint(point),
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
return actionManagerConfig;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private initRenderEvent(): void {
|
|
258
|
+
this.renderer.on('runtime-ready', (runtime: Runtime) => {
|
|
259
|
+
this.emit('runtime-ready', runtime);
|
|
260
|
+
});
|
|
261
|
+
this.renderer.on('page-el-update', (el: HTMLElement) => {
|
|
262
|
+
this.mask?.observe(el);
|
|
263
|
+
this.observePageResize(el);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private initMaskEvent(): void {
|
|
268
|
+
this.mask.on('change-guides', (data: GuidesEventData) => {
|
|
269
|
+
this.actionManager.setGuidelines(data.type, data.guides);
|
|
270
|
+
this.emit('change-guides', data);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
397
274
|
/**
|
|
398
|
-
*
|
|
275
|
+
* 初始化操作相关事件监听
|
|
399
276
|
*/
|
|
400
|
-
private
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
277
|
+
private initActionEvent(): void {
|
|
278
|
+
this.initActionManagerEvent();
|
|
279
|
+
this.initDrEvent();
|
|
280
|
+
this.initMulDrEvent();
|
|
281
|
+
this.initHighlightEvent();
|
|
405
282
|
}
|
|
406
283
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
284
|
+
/**
|
|
285
|
+
* 初始化ActionManager类本身抛出来的事件监听
|
|
286
|
+
*/
|
|
287
|
+
private initActionManagerEvent(): void {
|
|
288
|
+
this.actionManager
|
|
289
|
+
.on('before-select', (idOrEl: Id | HTMLElement, event?: MouseEvent) => {
|
|
290
|
+
this.select(idOrEl, event);
|
|
291
|
+
})
|
|
292
|
+
.on('select', (selectedEl: HTMLElement) => {
|
|
293
|
+
this.emit('select', selectedEl);
|
|
294
|
+
})
|
|
295
|
+
.on('before-multi-select', (idOrElList: HTMLElement[] | Id[]) => {
|
|
296
|
+
this.multiSelect(idOrElList);
|
|
297
|
+
})
|
|
298
|
+
.on('multi-select', (selectedElList: HTMLElement[]) => {
|
|
299
|
+
this.emit('multi-select', selectedElList);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* 初始化DragResize类通过ActionManager抛出来的事件监听
|
|
305
|
+
*/
|
|
306
|
+
private initDrEvent(): void {
|
|
307
|
+
this.actionManager
|
|
308
|
+
.on('update', (data: UpdateEventData) => {
|
|
309
|
+
this.emit('update', data);
|
|
310
|
+
})
|
|
311
|
+
.on('sort', (data: UpdateEventData) => {
|
|
312
|
+
this.emit('sort', data);
|
|
313
|
+
})
|
|
314
|
+
.on('select-parent', () => {
|
|
315
|
+
this.emit('select-parent');
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* 初始化MultiDragResize类通过ActionManager抛出来的事件监听
|
|
321
|
+
*/
|
|
322
|
+
private initMulDrEvent(): void {
|
|
323
|
+
this.actionManager
|
|
324
|
+
// 多选切换到单选
|
|
325
|
+
.on('change-to-select', (el: HTMLElement) => {
|
|
326
|
+
this.select(el);
|
|
327
|
+
// 先保证画布内完成渲染,再通知外部更新
|
|
328
|
+
setTimeout(() => this.emit('select', el));
|
|
329
|
+
})
|
|
330
|
+
.on('multi-update', (data: UpdateEventData, parentEl: HTMLElement | null) => {
|
|
331
|
+
this.emit('update', { data, parentEl });
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* 初始化Highlight类通过ActionManager抛出来的事件监听
|
|
337
|
+
*/
|
|
338
|
+
private initHighlightEvent(): void {
|
|
339
|
+
this.actionManager.on('highlight', async (highlightEl: HTMLElement) => {
|
|
340
|
+
this.emit('highlight', highlightEl);
|
|
341
|
+
});
|
|
414
342
|
}
|
|
415
343
|
}
|