@tmagic/stage 1.2.0-beta.2 → 1.2.0-beta.21

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.
Files changed (41) hide show
  1. package/README.md +62 -1
  2. package/dist/tmagic-stage.js +2157 -0
  3. package/dist/tmagic-stage.js.map +1 -0
  4. package/dist/{tmagic-stage.umd.js → tmagic-stage.umd.cjs} +1436 -993
  5. package/dist/tmagic-stage.umd.cjs.map +1 -0
  6. package/package.json +9 -8
  7. package/src/ActionManager.ts +534 -0
  8. package/src/DragResizeHelper.ts +338 -0
  9. package/src/MoveableOptionsManager.ts +249 -0
  10. package/src/MoveableSelectParentAble.ts +76 -0
  11. package/src/Rule.ts +13 -9
  12. package/src/StageCore.ts +220 -260
  13. package/src/StageDragResize.ts +83 -339
  14. package/src/StageHighlight.ts +17 -16
  15. package/src/StageMask.ts +88 -140
  16. package/src/StageMultiDragResize.ts +97 -198
  17. package/src/StageRender.ts +90 -15
  18. package/src/TargetShadow.ts +120 -0
  19. package/src/const.ts +1 -1
  20. package/src/types.ts +97 -19
  21. package/src/util.ts +24 -11
  22. package/types/ActionManager.d.ts +141 -0
  23. package/types/DragResizeHelper.d.ts +70 -0
  24. package/types/MoveableOptionsManager.d.ts +86 -0
  25. package/types/MoveableSelectParentAble.d.ts +8 -0
  26. package/types/Rule.d.ts +4 -3
  27. package/types/StageCore.d.ts +65 -39
  28. package/types/StageDragResize.d.ts +11 -40
  29. package/types/StageHighlight.d.ts +3 -4
  30. package/types/StageMask.d.ts +23 -22
  31. package/types/StageMultiDragResize.d.ts +8 -24
  32. package/types/StageRender.d.ts +24 -6
  33. package/types/TargetShadow.d.ts +22 -0
  34. package/types/const.d.ts +1 -1
  35. package/types/types.d.ts +85 -18
  36. package/types/util.d.ts +9 -8
  37. package/dist/tmagic-stage.mjs +0 -1715
  38. package/dist/tmagic-stage.mjs.map +0 -1
  39. package/dist/tmagic-stage.umd.js.map +0 -1
  40. package/src/TargetCalibrate.ts +0 -119
  41. package/types/TargetCalibrate.d.ts +0 -20
@@ -17,102 +17,62 @@
17
17
  */
18
18
 
19
19
  /* eslint-disable no-param-reassign */
20
- import { EventEmitter } from 'events';
20
+ import Moveable, { MoveableOptions } from 'moveable';
21
21
 
22
- import KeyController from 'keycon';
23
- import type { MoveableOptions } from 'moveable';
24
- import Moveable from 'moveable';
25
- import MoveableHelper from 'moveable-helper';
26
-
27
- import { removeClassNameByClassName } from '@tmagic/utils';
28
-
29
- import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
30
- import StageCore from './StageCore';
31
- import StageMask from './StageMask';
32
- import type { StageDragResizeConfig } from './types';
33
- import { ContainerHighlightType, StageDragStatus } from './types';
34
- import { calcValueByFontsize, down, getAbsolutePosition, getMode, getOffset, getTargetElStyle, up } from './util';
22
+ import { Mode } from './const';
23
+ import DragResizeHelper from './DragResizeHelper';
24
+ import MoveableOptionsManager from './MoveableOptionsManager';
25
+ import type { DelayedMarkContainer, GetRenderDocument, MarkContainerEnd, StageDragResizeConfig } from './types';
26
+ import { StageDragStatus } from './types';
27
+ import { calcValueByFontsize, down, getMode, getOffset, up } from './util';
35
28
 
36
29
  /**
37
- * 选中框
30
+ * 管理单选操作,响应选中操作,初始化moveableOption参数并初始化moveable,处理moveable回调事件对组件进行更新
31
+ * @extends MoveableOptionsManager
38
32
  */
39
- export default class StageDragResize extends EventEmitter {
40
- public core: StageCore;
41
- public mask: StageMask;
42
- /** 画布容器 */
43
- public container: HTMLElement;
33
+ export default class StageDragResize extends MoveableOptionsManager {
44
34
  /** 目标节点 */
45
- public target?: HTMLElement;
46
- /** 目标节点在蒙层中的占位节点 */
47
- public dragEl?: HTMLDivElement;
35
+ private target?: HTMLElement;
48
36
  /** Moveable拖拽类实例 */
49
- public moveable?: Moveable;
50
- /** 水平参考线 */
51
- public horizontalGuidelines: number[] = [];
52
- /** 垂直参考线 */
53
- public verticalGuidelines: number[] = [];
54
- /** 对齐元素集合 */
55
- public elementGuidelines: HTMLElement[] = [];
56
- /** 布局方式:流式布局、绝对定位、固定定位 */
57
- public mode: Mode = Mode.ABSOLUTE;
58
-
59
- private moveableOptions: MoveableOptions = {};
37
+ private moveable?: Moveable;
60
38
  /** 拖动状态 */
61
39
  private dragStatus: StageDragStatus = StageDragStatus.END;
62
- /** 流式布局下,目标节点的镜像节点 */
63
- private ghostEl: HTMLElement | undefined;
64
- private moveableHelper?: MoveableHelper;
65
- private isContainerHighlight: Boolean = false;
40
+ private dragResizeHelper: DragResizeHelper;
41
+ private getRenderDocument: GetRenderDocument;
42
+ private markContainerEnd: MarkContainerEnd;
43
+ private delayedMarkContainer: DelayedMarkContainer;
66
44
 
67
45
  constructor(config: StageDragResizeConfig) {
68
- super();
46
+ super(config);
69
47
 
70
- this.core = config.core;
71
- this.container = config.container;
72
- this.mask = config.mask;
48
+ this.getRenderDocument = config.getRenderDocument;
49
+ this.markContainerEnd = config.markContainerEnd;
50
+ this.delayedMarkContainer = config.delayedMarkContainer;
73
51
 
74
- KeyController.global.keydown('alt', (e) => {
75
- e.inputEvent.preventDefault();
76
- this.isContainerHighlight = true;
52
+ this.dragResizeHelper = new DragResizeHelper({
53
+ container: config.container,
54
+ updateDragEl: config.updateDragEl,
77
55
  });
78
- KeyController.global.keyup('alt', (e) => {
79
- e.inputEvent.preventDefault();
80
56
 
81
- const doc = this.core.renderer.contentWindow?.document;
82
- if (doc && this.canContainerHighlight()) {
83
- removeClassNameByClassName(doc, this.core.containerHighlightClassName);
57
+ this.on('update-moveable', () => {
58
+ if (this.moveable) {
59
+ this.updateMoveable();
84
60
  }
85
- this.isContainerHighlight = false;
86
61
  });
87
62
  }
88
63
 
89
64
  /**
90
65
  * 将选中框渲染并覆盖到选中的组件Dom节点上方
91
- * 当选中的节点是不是absolute时,会创建一个新的节点出来作为拖拽目标
66
+ * 当选中的节点不是absolute时,会创建一个新的节点出来作为拖拽目标
92
67
  * @param el 选中组件的Dom节点元素
93
68
  * @param event 鼠标事件
94
69
  */
95
70
  public select(el: HTMLElement, event?: MouseEvent): void {
96
- const oldTarget = this.target;
97
- this.target = el;
98
-
99
- if (!this.dragEl) {
100
- this.dragEl = globalThis.document.createElement('div');
101
- this.container.append(this.dragEl);
102
- }
103
-
104
71
  // 从不能拖动到能拖动的节点之间切换,要重新创建moveable,不然dragStart不生效
105
- if (!this.moveable || this.target !== oldTarget) {
106
- this.init(el);
107
- this.moveableHelper = MoveableHelper.create({
108
- useBeforeRender: true,
109
- useRender: false,
110
- createAuto: true,
111
- });
112
-
113
- this.initMoveable();
72
+ if (!this.moveable || el !== this.target) {
73
+ this.initMoveable(el);
114
74
  } else {
115
- this.updateMoveable();
75
+ this.updateMoveable(el);
116
76
  }
117
77
 
118
78
  if (event) {
@@ -124,120 +84,63 @@ export default class StageDragResize extends EventEmitter {
124
84
  * 初始化选中框并渲染出来
125
85
  */
126
86
  public updateMoveable(el = this.target): void {
127
- if (!this.moveable) throw new Error('未初始化moveable');
87
+ if (!this.moveable) return;
128
88
  if (!el) throw new Error('未选中任何节点');
129
89
 
130
- this.target = el;
131
-
132
- this.init(el);
90
+ const options: MoveableOptions = this.init(el);
133
91
 
134
- Object.entries(this.moveableOptions).forEach(([key, value]) => {
92
+ Object.entries(options).forEach(([key, value]) => {
135
93
  (this.moveable as any)[key] = value;
136
94
  });
137
95
  this.moveable.updateTarget();
138
96
  }
139
97
 
140
- public setGuidelines(type: GuidesType, guidelines: number[]): void {
141
- if (type === GuidesType.HORIZONTAL) {
142
- this.horizontalGuidelines = guidelines;
143
- this.moveableOptions.horizontalGuidelines = guidelines;
144
- } else if (type === GuidesType.VERTICAL) {
145
- this.verticalGuidelines = guidelines;
146
- this.moveableOptions.verticalGuidelines = guidelines;
147
- }
148
-
149
- if (this.moveable) {
150
- this.updateMoveable();
151
- }
152
- }
153
-
154
- public clearGuides() {
155
- this.horizontalGuidelines = [];
156
- this.verticalGuidelines = [];
157
- this.moveableOptions.horizontalGuidelines = [];
158
- this.moveableOptions.verticalGuidelines = [];
159
- this.updateMoveable();
160
- }
161
-
162
98
  public clearSelectStatus(): void {
163
99
  if (!this.moveable) return;
164
- this.destroyDragEl();
165
- this.dragEl = undefined;
100
+ this.dragResizeHelper.destroyShadowEl();
166
101
  this.moveable.target = null;
167
102
  this.moveable.updateTarget();
168
103
  }
169
104
 
170
- public destroyDragEl(): void {
171
- this.dragEl?.remove();
172
- }
173
-
174
105
  /**
175
106
  * 销毁实例
176
107
  */
177
108
  public destroy(): void {
178
109
  this.moveable?.destroy();
179
- this.destroyGhostEl();
180
- this.destroyDragEl();
110
+ this.dragResizeHelper.destroy();
181
111
  this.dragStatus = StageDragStatus.END;
182
112
  this.removeAllListeners();
183
113
  }
184
114
 
185
- private init(el: HTMLElement): void {
115
+ private init(el: HTMLElement): MoveableOptions {
186
116
  // 如果有滚动条会导致resize时获取到width,height不准确
187
117
  if (/(auto|scroll)/.test(el.style.overflow)) {
188
118
  el.style.overflow = 'hidden';
189
119
  }
190
- this.mode = getMode(el);
191
-
192
- this.destroyGhostEl();
193
120
 
194
- if (!this.dragEl) {
195
- return;
196
- }
121
+ this.target = el;
122
+ this.mode = getMode(el);
197
123
 
198
- this.dragEl.style.cssText = getTargetElStyle(el);
199
- this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
124
+ this.dragResizeHelper.updateShadowEl(el);
125
+ this.dragResizeHelper.setMode(this.mode);
200
126
 
201
- if (typeof this.core.config.updateDragEl === 'function') {
202
- this.core.config.updateDragEl(this.dragEl, el);
203
- }
204
- this.moveableOptions = this.getOptions({
205
- target: this.dragEl,
206
- });
207
- }
127
+ // 设置选中元素的周围元素,用于选中元素跟周围元素对齐辅助
128
+ const elementGuidelines: HTMLElement[] = Array.prototype.slice.call(this.target?.parentElement?.children) || [];
129
+ this.setElementGuidelines([this.target as HTMLElement], elementGuidelines);
208
130
 
209
- private setElementGuidelines(nodes: HTMLElement[]) {
210
- this.elementGuidelines.forEach((node) => {
211
- node.remove();
131
+ return this.getOptions(false, {
132
+ target: this.dragResizeHelper.getShadowEl(),
212
133
  });
213
- this.elementGuidelines = [];
214
-
215
- if (this.mode === Mode.ABSOLUTE) {
216
- this.container.append(this.createGuidelineElements(nodes));
217
- }
218
134
  }
219
135
 
220
- private createGuidelineElements(nodes: HTMLElement[]) {
221
- const frame = globalThis.document.createDocumentFragment();
222
-
223
- for (const node of nodes) {
224
- const { width, height } = node.getBoundingClientRect();
225
- if (node === this.target) continue;
226
- const { left, top } = getOffset(node as HTMLElement);
227
- const elementGuideline = globalThis.document.createElement('div');
228
- elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
229
- this.elementGuidelines.push(elementGuideline);
230
- frame.append(elementGuideline);
231
- }
232
-
233
- return frame;
234
- }
136
+ private initMoveable(el: HTMLElement) {
137
+ const options: MoveableOptions = this.init(el);
138
+ this.dragResizeHelper.clear();
235
139
 
236
- private initMoveable() {
237
140
  this.moveable?.destroy();
238
141
 
239
142
  this.moveable = new Moveable(this.container, {
240
- ...this.moveableOptions,
143
+ ...options,
241
144
  });
242
145
 
243
146
  this.bindResizeEvent();
@@ -249,41 +152,19 @@ export default class StageDragResize extends EventEmitter {
249
152
  private bindResizeEvent(): void {
250
153
  if (!this.moveable) throw new Error('moveable 未初始化');
251
154
 
252
- const frame = {
253
- left: 0,
254
- top: 0,
255
- };
256
-
257
155
  this.moveable
258
156
  .on('resizeStart', (e) => {
259
157
  if (!this.target) return;
260
158
 
261
159
  this.dragStatus = StageDragStatus.START;
262
- this.moveableHelper?.onResizeStart(e);
263
-
264
- frame.top = this.target.offsetTop;
265
- frame.left = this.target.offsetLeft;
160
+ this.dragResizeHelper.onResizeStart(e);
266
161
  })
267
162
  .on('resize', (e) => {
268
- const { width, height, drag } = e;
269
- if (!this.moveable || !this.target || !this.dragEl) return;
163
+ if (!this.moveable || !this.target || !this.dragResizeHelper.getShadowEl()) return;
270
164
 
271
- const { beforeTranslate } = drag;
272
165
  this.dragStatus = StageDragStatus.ING;
273
166
 
274
- // 流式布局
275
- if (this.mode === Mode.SORTABLE) {
276
- this.target.style.top = '0px';
277
- this.dragEl.style.width = `${width}px`;
278
- this.dragEl.style.height = `${height}px`;
279
- } else {
280
- this.moveableHelper?.onResize(e);
281
- this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
282
- this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
283
- }
284
-
285
- this.target.style.width = `${width}px`;
286
- this.target.style.height = `${height}px`;
167
+ this.dragResizeHelper.onResize(e);
287
168
  })
288
169
  .on('resizeEnd', () => {
289
170
  this.dragStatus = StageDragStatus.END;
@@ -294,55 +175,28 @@ export default class StageDragResize extends EventEmitter {
294
175
  private bindDragEvent(): void {
295
176
  if (!this.moveable) throw new Error('moveable 未初始化');
296
177
 
297
- const frame = {
298
- left: 0,
299
- top: 0,
300
- };
301
-
302
178
  let timeout: NodeJS.Timeout | undefined;
303
179
 
304
- const { contentWindow } = this.core.renderer;
305
- const doc = contentWindow?.document;
306
-
307
180
  this.moveable
308
181
  .on('dragStart', (e) => {
309
182
  if (!this.target) throw new Error('未选中组件');
310
183
 
311
184
  this.dragStatus = StageDragStatus.START;
312
185
 
313
- this.moveableHelper?.onDragStart(e);
314
-
315
- if (this.mode === Mode.SORTABLE) {
316
- this.ghostEl = this.generateGhostEl(this.target);
317
- }
318
-
319
- frame.top = this.target.offsetTop;
320
- frame.left = this.target.offsetLeft;
186
+ this.dragResizeHelper.onDragStart(e);
321
187
  })
322
188
  .on('drag', (e) => {
323
- if (!this.target || !this.dragEl) return;
189
+ if (!this.target || !this.dragResizeHelper.getShadowEl()) return;
324
190
 
325
191
  if (timeout) {
326
192
  globalThis.clearTimeout(timeout);
327
193
  timeout = undefined;
328
194
  }
329
-
330
- if (this.canContainerHighlight()) {
331
- timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
332
- }
195
+ timeout = this.delayedMarkContainer(e.inputEvent, [this.target]);
333
196
 
334
197
  this.dragStatus = StageDragStatus.ING;
335
198
 
336
- // 流式布局
337
- if (this.ghostEl) {
338
- this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
339
- return;
340
- }
341
-
342
- this.moveableHelper?.onDrag(e);
343
-
344
- this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
345
- this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
199
+ this.dragResizeHelper.onDrag(e);
346
200
  })
347
201
  .on('dragEnd', () => {
348
202
  if (timeout) {
@@ -350,12 +204,7 @@ export default class StageDragResize extends EventEmitter {
350
204
  timeout = undefined;
351
205
  }
352
206
 
353
- let parentEl: HTMLElement | null = null;
354
-
355
- if (doc && this.canContainerHighlight()) {
356
- parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
357
- }
358
-
207
+ const parentEl = this.markContainerEnd();
359
208
  // 点击不拖动时会触发dragStart和dragEnd,但是不会有drag事件
360
209
  if (this.dragStatus === StageDragStatus.ING) {
361
210
  if (parentEl) {
@@ -372,7 +221,7 @@ export default class StageDragResize extends EventEmitter {
372
221
  }
373
222
 
374
223
  this.dragStatus = StageDragStatus.END;
375
- this.destroyGhostEl();
224
+ this.dragResizeHelper.destroyGhostEl();
376
225
  });
377
226
  }
378
227
 
@@ -382,18 +231,16 @@ export default class StageDragResize extends EventEmitter {
382
231
  this.moveable
383
232
  .on('rotateStart', (e) => {
384
233
  this.dragStatus = StageDragStatus.START;
385
- this.moveableHelper?.onRotateStart(e);
234
+ this.dragResizeHelper.onRotateStart(e);
386
235
  })
387
236
  .on('rotate', (e) => {
388
- if (!this.target || !this.dragEl) return;
237
+ if (!this.target || !this.dragResizeHelper.getShadowEl()) return;
389
238
  this.dragStatus = StageDragStatus.ING;
390
- this.moveableHelper?.onRotate(e);
391
- const frame = this.moveableHelper?.getFrame(e.target);
392
- this.target.style.transform = frame?.toCSSObject().transform || '';
239
+ this.dragResizeHelper.onRotate(e);
393
240
  })
394
241
  .on('rotateEnd', (e) => {
395
242
  this.dragStatus = StageDragStatus.END;
396
- const frame = this.moveableHelper?.getFrame(e.target);
243
+ const frame = this.dragResizeHelper?.getFrame(e.target);
397
244
  this.emit('update', {
398
245
  data: [
399
246
  {
@@ -413,18 +260,16 @@ export default class StageDragResize extends EventEmitter {
413
260
  this.moveable
414
261
  .on('scaleStart', (e) => {
415
262
  this.dragStatus = StageDragStatus.START;
416
- this.moveableHelper?.onScaleStart(e);
263
+ this.dragResizeHelper.onScaleStart(e);
417
264
  })
418
265
  .on('scale', (e) => {
419
- if (!this.target || !this.dragEl) return;
266
+ if (!this.target || !this.dragResizeHelper.getShadowEl()) return;
420
267
  this.dragStatus = StageDragStatus.ING;
421
- this.moveableHelper?.onScale(e);
422
- const frame = this.moveableHelper?.getFrame(e.target);
423
- this.target.style.transform = frame?.toCSSObject().transform || '';
268
+ this.dragResizeHelper.onScale(e);
424
269
  })
425
270
  .on('scaleEnd', (e) => {
426
271
  this.dragStatus = StageDragStatus.END;
427
- const frame = this.moveableHelper?.getFrame(e.target);
272
+ const frame = this.dragResizeHelper.getFrame(e.target);
428
273
  this.emit('update', {
429
274
  data: [
430
275
  {
@@ -439,8 +284,8 @@ export default class StageDragResize extends EventEmitter {
439
284
  }
440
285
 
441
286
  private sort(): void {
442
- if (!this.target || !this.ghostEl) throw new Error('未知错误');
443
- const { top } = this.ghostEl.getBoundingClientRect();
287
+ if (!this.target || !this.dragResizeHelper.getGhostEl()) throw new Error('未知错误');
288
+ const { top } = this.dragResizeHelper.getGhostEl()!.getBoundingClientRect();
444
289
  const { top: oriTop } = this.target.getBoundingClientRect();
445
290
  const deltaTop = top - oriTop;
446
291
  if (Math.abs(deltaTop) >= this.target.clientHeight / 2) {
@@ -460,8 +305,7 @@ export default class StageDragResize extends EventEmitter {
460
305
  private update(isResize = false, parentEl: HTMLElement | null = null): void {
461
306
  if (!this.target) return;
462
307
 
463
- const { contentWindow } = this.core.renderer;
464
- const doc = contentWindow?.document;
308
+ const doc = this.getRenderDocument();
465
309
 
466
310
  if (!doc) return;
467
311
 
@@ -473,15 +317,25 @@ export default class StageDragResize extends EventEmitter {
473
317
  const width = calcValueByFontsize(doc, this.target.clientWidth);
474
318
  const height = calcValueByFontsize(doc, this.target.clientHeight);
475
319
 
476
- if (parentEl && this.mode === Mode.ABSOLUTE && this.dragEl) {
477
- const [translateX, translateY] = this.moveableHelper?.getFrame(this.dragEl).properties.transform.translate.value;
320
+ const shadowEl = this.dragResizeHelper.getShadowEl();
321
+ if (parentEl && this.mode === Mode.ABSOLUTE && shadowEl) {
322
+ const targetShadowHtmlEl = shadowEl as HTMLElement;
323
+ const targetShadowElOffsetLeft = targetShadowHtmlEl.offsetLeft || 0;
324
+ const targetShadowElOffsetTop = targetShadowHtmlEl.offsetTop || 0;
325
+
326
+ const frame = this.dragResizeHelper.getFrame(shadowEl);
327
+
328
+ const [translateX, translateY] = frame?.properties.transform.translate.value;
478
329
  const { left: parentLeft, top: parentTop } = getOffset(parentEl);
330
+
479
331
  left =
480
- calcValueByFontsize(doc, this.dragEl.offsetLeft) +
332
+ calcValueByFontsize(doc, targetShadowElOffsetLeft) +
481
333
  parseFloat(translateX) -
482
334
  calcValueByFontsize(doc, parentLeft);
483
335
  top =
484
- calcValueByFontsize(doc, this.dragEl.offsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
336
+ calcValueByFontsize(doc, targetShadowElOffsetTop) +
337
+ parseFloat(translateY) -
338
+ calcValueByFontsize(doc, parentTop);
485
339
  }
486
340
 
487
341
  this.emit('update', {
@@ -494,114 +348,4 @@ export default class StageDragResize extends EventEmitter {
494
348
  parentEl,
495
349
  });
496
350
  }
497
-
498
- private generateGhostEl(el: HTMLElement): HTMLElement {
499
- if (this.ghostEl) {
500
- this.destroyGhostEl();
501
- }
502
-
503
- const ghostEl = el.cloneNode(true) as HTMLElement;
504
- this.setGhostElChildrenId(ghostEl);
505
- const { top, left } = getAbsolutePosition(el, getOffset(el));
506
- ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
507
- ghostEl.style.zIndex = ZIndex.GHOST_EL;
508
- ghostEl.style.opacity = '.5';
509
- ghostEl.style.position = 'absolute';
510
- ghostEl.style.left = `${left}px`;
511
- ghostEl.style.top = `${top}px`;
512
- el.after(ghostEl);
513
- return ghostEl;
514
- }
515
-
516
- private setGhostElChildrenId(el: Element) {
517
- for (const child of Array.from(el.children)) {
518
- if (child.id) {
519
- child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
520
- }
521
-
522
- if (child.children.length) {
523
- this.setGhostElChildrenId(child);
524
- }
525
- }
526
- }
527
-
528
- private destroyGhostEl(): void {
529
- this.ghostEl?.remove();
530
- this.ghostEl = undefined;
531
- }
532
-
533
- private getOptions(options: MoveableOptions = {}): MoveableOptions {
534
- if (!this.target) return {};
535
-
536
- const isAbsolute = this.mode === Mode.ABSOLUTE;
537
- const isFixed = this.mode === Mode.FIXED;
538
- const isSortable = this.mode === Mode.SORTABLE;
539
-
540
- let { moveableOptions = {} } = this.core.config;
541
-
542
- if (typeof moveableOptions === 'function') {
543
- moveableOptions = moveableOptions(this.core);
544
- }
545
-
546
- const elementGuidelines: any = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
547
-
548
- this.setElementGuidelines(elementGuidelines);
549
-
550
- if (moveableOptions.elementGuidelines) {
551
- delete moveableOptions.elementGuidelines;
552
- }
553
-
554
- return {
555
- origin: false,
556
- rootContainer: this.core.container,
557
- zoom: 1,
558
- dragArea: false,
559
- draggable: true,
560
- resizable: true,
561
- scalable: false,
562
- rotatable: false,
563
- snappable: isAbsolute || isFixed,
564
- snapGap: isAbsolute || isFixed,
565
- snapThreshold: 5,
566
- snapDigit: 0,
567
- throttleDrag: 0,
568
- isDisplaySnapDigit: isAbsolute,
569
- snapDirections: {
570
- top: isAbsolute,
571
- right: isAbsolute,
572
- bottom: isAbsolute,
573
- left: isAbsolute,
574
- center: isAbsolute,
575
- middle: isAbsolute,
576
- },
577
- elementSnapDirections: {
578
- top: isAbsolute,
579
- right: isAbsolute,
580
- bottom: isAbsolute,
581
- left: isAbsolute,
582
- },
583
- isDisplayInnerSnapDigit: true,
584
- horizontalGuidelines: this.horizontalGuidelines,
585
- verticalGuidelines: this.verticalGuidelines,
586
- elementGuidelines: this.elementGuidelines,
587
-
588
- bounds: {
589
- top: 0,
590
- // 设置0的话无法移动到left为0,所以只能设置为-1
591
- left: -1,
592
- right: this.container.clientWidth - 1,
593
- bottom: isSortable ? undefined : this.container.clientHeight,
594
- ...(moveableOptions.bounds || {}),
595
- },
596
- ...options,
597
- ...moveableOptions,
598
- };
599
- }
600
-
601
- private canContainerHighlight() {
602
- return (
603
- this.core.containerHighlightType === ContainerHighlightType.DEFAULT ||
604
- (this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight)
605
- );
606
- }
607
351
  }
@@ -20,27 +20,28 @@ import { EventEmitter } from 'events';
20
20
 
21
21
  import Moveable from 'moveable';
22
22
 
23
- import { HIGHLIGHT_EL_ID_PREFIX } from './const';
24
- import StageCore from './StageCore';
25
- import TargetCalibrate from './TargetCalibrate';
26
- import type { StageHighlightConfig } from './types';
23
+ import { HIGHLIGHT_EL_ID_PREFIX, ZIndex } from './const';
24
+ import TargetShadow from './TargetShadow';
25
+ import type { GetRootContainer, StageHighlightConfig } from './types';
26
+
27
27
  export default class StageHighlight extends EventEmitter {
28
- public core: StageCore;
29
28
  public container: HTMLElement;
30
29
  public target?: HTMLElement;
31
30
  public moveable?: Moveable;
32
- public calibrationTarget: TargetCalibrate;
31
+ public targetShadow: TargetShadow;
32
+ private getRootContainer: GetRootContainer;
33
33
 
34
34
  constructor(config: StageHighlightConfig) {
35
35
  super();
36
36
 
37
- this.core = config.core;
38
37
  this.container = config.container;
39
- this.calibrationTarget = new TargetCalibrate({
40
- parent: this.core.mask.content,
41
- mask: this.core.mask,
42
- dr: this.core.dr,
43
- core: this.core,
38
+ this.getRootContainer = config.getRootContainer;
39
+
40
+ this.targetShadow = new TargetShadow({
41
+ container: config.container,
42
+ updateDragEl: config.updateDragEl,
43
+ zIndex: ZIndex.HIGHLIGHT_EL,
44
+ idPrefix: HIGHLIGHT_EL_ID_PREFIX,
44
45
  });
45
46
  }
46
47
 
@@ -54,9 +55,9 @@ export default class StageHighlight extends EventEmitter {
54
55
  this.moveable?.destroy();
55
56
 
56
57
  this.moveable = new Moveable(this.container, {
57
- target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
58
+ target: this.targetShadow.update(el),
58
59
  origin: false,
59
- rootContainer: this.core.container,
60
+ rootContainer: this.getRootContainer(),
60
61
  zoom: 2,
61
62
  });
62
63
  }
@@ -65,7 +66,7 @@ export default class StageHighlight extends EventEmitter {
65
66
  * 清空高亮
66
67
  */
67
68
  public clearHighlight(): void {
68
- if (!this.moveable) return;
69
+ if (!this.moveable || !this.target) return;
69
70
  this.target = undefined;
70
71
  this.moveable.target = null;
71
72
  this.moveable.updateTarget();
@@ -76,6 +77,6 @@ export default class StageHighlight extends EventEmitter {
76
77
  */
77
78
  public destroy(): void {
78
79
  this.moveable?.destroy();
79
- this.calibrationTarget.destroy();
80
+ this.targetShadow.destroy();
80
81
  }
81
82
  }