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