@tmagic/stage 1.0.6 → 1.1.0-beta.10

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.
@@ -19,36 +19,32 @@
19
19
  /* eslint-disable no-param-reassign */
20
20
  import { EventEmitter } from 'events';
21
21
 
22
+ import KeyController from 'keycon';
22
23
  import type { MoveableOptions } from 'moveable';
23
24
  import Moveable from 'moveable';
24
25
  import MoveableHelper from 'moveable-helper';
25
26
 
27
+ import { removeClassNameByClassName } from '@tmagic/utils';
28
+
26
29
  import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
27
30
  import StageCore from './StageCore';
28
- import type { SortEventData, StageDragResizeConfig } from './types';
29
- import { getAbsolutePosition, getMode, getOffset } from './util';
30
-
31
- /** 拖动状态 */
32
- enum ActionStatus {
33
- /** 开始拖动 */
34
- START = 'start',
35
- /** 拖动中 */
36
- ING = 'ing',
37
- /** 拖动结束 */
38
- END = 'end',
39
- }
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';
40
35
 
41
36
  /**
42
37
  * 选中框
43
38
  */
44
39
  export default class StageDragResize extends EventEmitter {
45
40
  public core: StageCore;
41
+ public mask: StageMask;
46
42
  /** 画布容器 */
47
43
  public container: HTMLElement;
48
44
  /** 目标节点 */
49
45
  public target?: HTMLElement;
50
46
  /** 目标节点在蒙层中的占位节点 */
51
- public dragEl: HTMLDivElement;
47
+ public dragEl?: HTMLDivElement;
52
48
  /** Moveable拖拽类实例 */
53
49
  public moveable?: Moveable;
54
50
  /** 水平参考线 */
@@ -62,19 +58,32 @@ export default class StageDragResize extends EventEmitter {
62
58
 
63
59
  private moveableOptions: MoveableOptions = {};
64
60
  /** 拖动状态 */
65
- private dragStatus: ActionStatus = ActionStatus.END;
61
+ private dragStatus: StageDragStatus = StageDragStatus.END;
66
62
  /** 流式布局下,目标节点的镜像节点 */
67
63
  private ghostEl: HTMLElement | undefined;
68
64
  private moveableHelper?: MoveableHelper;
65
+ private isContainerHighlight: Boolean = false;
69
66
 
70
67
  constructor(config: StageDragResizeConfig) {
71
68
  super();
72
69
 
73
70
  this.core = config.core;
74
71
  this.container = config.container;
72
+ this.mask = config.mask;
75
73
 
76
- this.dragEl = globalThis.document.createElement('div');
77
- this.container.append(this.dragEl);
74
+ KeyController.global.keydown('alt', (e) => {
75
+ e.inputEvent.preventDefault();
76
+ this.isContainerHighlight = true;
77
+ });
78
+ KeyController.global.keyup('alt', (e) => {
79
+ e.inputEvent.preventDefault();
80
+
81
+ const doc = this.core.renderer.contentWindow?.document;
82
+ if (doc && this.canContainerHighlight()) {
83
+ removeClassNameByClassName(doc, this.core.containerHighlightClassName);
84
+ }
85
+ this.isContainerHighlight = false;
86
+ });
78
87
  }
79
88
 
80
89
  /**
@@ -145,6 +154,17 @@ export default class StageDragResize extends EventEmitter {
145
154
  this.updateMoveable();
146
155
  }
147
156
 
157
+ public clearSelectStatus(): void {
158
+ if (!this.moveable) return;
159
+ this.destroyDragEl();
160
+ this.moveable.target = null;
161
+ this.moveable.updateTarget();
162
+ }
163
+
164
+ public destroyDragEl(): void {
165
+ this.dragEl?.remove();
166
+ }
167
+
148
168
  /**
149
169
  * 销毁实例
150
170
  */
@@ -152,7 +172,7 @@ export default class StageDragResize extends EventEmitter {
152
172
  this.moveable?.destroy();
153
173
  this.destroyGhostEl();
154
174
  this.destroyDragEl();
155
- this.dragStatus = ActionStatus.END;
175
+ this.dragStatus = StageDragStatus.END;
156
176
  this.removeAllListeners();
157
177
  }
158
178
 
@@ -164,9 +184,15 @@ export default class StageDragResize extends EventEmitter {
164
184
  this.mode = getMode(el);
165
185
 
166
186
  this.destroyGhostEl();
187
+ this.destroyDragEl();
188
+ this.dragEl = globalThis.document.createElement('div');
189
+ this.container.append(this.dragEl);
190
+ this.dragEl.style.cssText = getTargetElStyle(el);
191
+ this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
167
192
 
168
- this.updateDragEl(el);
169
-
193
+ if (typeof this.core.config.updateDragEl === 'function') {
194
+ this.core.config.updateDragEl(this.dragEl, el);
195
+ }
170
196
  this.moveableOptions = this.getOptions({
171
197
  target: this.dragEl,
172
198
  });
@@ -179,20 +205,24 @@ export default class StageDragResize extends EventEmitter {
179
205
  this.elementGuidelines = [];
180
206
 
181
207
  if (this.mode === Mode.ABSOLUTE) {
182
- const frame = document.createDocumentFragment();
183
-
184
- for (const node of nodes) {
185
- const { width, height } = node.getBoundingClientRect();
186
- if (node === this.target) continue;
187
- const { left, top } = getOffset(node as HTMLElement);
188
- const elementGuideline = document.createElement('div');
189
- elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
190
- this.elementGuidelines.push(elementGuideline);
191
- frame.append(elementGuideline);
192
- }
208
+ this.container.append(this.createGuidelineElements(nodes));
209
+ }
210
+ }
193
211
 
194
- this.container.append(frame);
212
+ private createGuidelineElements(nodes: HTMLElement[]) {
213
+ const frame = globalThis.document.createDocumentFragment();
214
+
215
+ for (const node of nodes) {
216
+ const { width, height } = node.getBoundingClientRect();
217
+ if (node === this.target) continue;
218
+ const { left, top } = getOffset(node as HTMLElement);
219
+ const elementGuideline = globalThis.document.createElement('div');
220
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
221
+ this.elementGuidelines.push(elementGuideline);
222
+ frame.append(elementGuideline);
195
223
  }
224
+
225
+ return frame;
196
226
  }
197
227
 
198
228
  private initMoveable() {
@@ -220,7 +250,7 @@ export default class StageDragResize extends EventEmitter {
220
250
  .on('resizeStart', (e) => {
221
251
  if (!this.target) return;
222
252
 
223
- this.dragStatus = ActionStatus.START;
253
+ this.dragStatus = StageDragStatus.START;
224
254
  this.moveableHelper?.onResizeStart(e);
225
255
 
226
256
  frame.top = this.target.offsetTop;
@@ -231,7 +261,7 @@ export default class StageDragResize extends EventEmitter {
231
261
  if (!this.moveable || !this.target || !this.dragEl) return;
232
262
 
233
263
  const { beforeTranslate } = drag;
234
- this.dragStatus = ActionStatus.ING;
264
+ this.dragStatus = StageDragStatus.ING;
235
265
 
236
266
  this.moveableHelper?.onResize(e);
237
267
 
@@ -247,7 +277,7 @@ export default class StageDragResize extends EventEmitter {
247
277
  this.target.style.height = `${height}px`;
248
278
  })
249
279
  .on('resizeEnd', () => {
250
- this.dragStatus = ActionStatus.END;
280
+ this.dragStatus = StageDragStatus.END;
251
281
  this.update(true);
252
282
  });
253
283
  }
@@ -260,11 +290,16 @@ export default class StageDragResize extends EventEmitter {
260
290
  top: 0,
261
291
  };
262
292
 
293
+ let timeout: NodeJS.Timeout | undefined;
294
+
295
+ const { contentWindow } = this.core.renderer;
296
+ const doc = contentWindow?.document;
297
+
263
298
  this.moveable
264
299
  .on('dragStart', (e) => {
265
300
  if (!this.target) throw new Error('未选中组件');
266
301
 
267
- this.dragStatus = ActionStatus.START;
302
+ this.dragStatus = StageDragStatus.START;
268
303
 
269
304
  this.moveableHelper?.onDragStart(e);
270
305
 
@@ -278,7 +313,16 @@ export default class StageDragResize extends EventEmitter {
278
313
  .on('drag', (e) => {
279
314
  if (!this.target || !this.dragEl) return;
280
315
 
281
- this.dragStatus = ActionStatus.ING;
316
+ if (timeout) {
317
+ globalThis.clearTimeout(timeout);
318
+ timeout = undefined;
319
+ }
320
+
321
+ if (this.canContainerHighlight()) {
322
+ timeout = this.core.getAddContainerHighlightClassNameTimeout(e.inputEvent, [this.target]);
323
+ }
324
+
325
+ this.dragStatus = StageDragStatus.ING;
282
326
 
283
327
  // 流式布局
284
328
  if (this.ghostEl) {
@@ -292,18 +336,33 @@ export default class StageDragResize extends EventEmitter {
292
336
  this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
293
337
  })
294
338
  .on('dragEnd', () => {
339
+ if (timeout) {
340
+ globalThis.clearTimeout(timeout);
341
+ timeout = undefined;
342
+ }
343
+
344
+ let parentEl: HTMLElement | null = null;
345
+
346
+ if (doc && this.canContainerHighlight()) {
347
+ parentEl = removeClassNameByClassName(doc, this.core.containerHighlightClassName);
348
+ }
349
+
295
350
  // 点击不拖动时会触发dragStart和dragEnd,但是不会有drag事件
296
- if (this.dragStatus === ActionStatus.ING) {
297
- switch (this.mode) {
298
- case Mode.SORTABLE:
299
- this.sort();
300
- break;
301
- default:
302
- this.update();
351
+ if (this.dragStatus === StageDragStatus.ING) {
352
+ if (parentEl) {
353
+ this.update(false, parentEl);
354
+ } else {
355
+ switch (this.mode) {
356
+ case Mode.SORTABLE:
357
+ this.sort();
358
+ break;
359
+ default:
360
+ this.update();
361
+ }
303
362
  }
304
363
  }
305
364
 
306
- this.dragStatus = ActionStatus.END;
365
+ this.dragStatus = StageDragStatus.END;
307
366
  this.destroyGhostEl();
308
367
  });
309
368
  }
@@ -313,18 +372,18 @@ export default class StageDragResize extends EventEmitter {
313
372
 
314
373
  this.moveable
315
374
  .on('rotateStart', (e) => {
316
- this.dragStatus = ActionStatus.START;
375
+ this.dragStatus = StageDragStatus.START;
317
376
  this.moveableHelper?.onRotateStart(e);
318
377
  })
319
378
  .on('rotate', (e) => {
320
379
  if (!this.target || !this.dragEl) return;
321
- this.dragStatus = ActionStatus.ING;
380
+ this.dragStatus = StageDragStatus.ING;
322
381
  this.moveableHelper?.onRotate(e);
323
382
  const frame = this.moveableHelper?.getFrame(e.target);
324
383
  this.target.style.transform = frame?.toCSSObject().transform || '';
325
384
  })
326
385
  .on('rotateEnd', (e) => {
327
- this.dragStatus = ActionStatus.END;
386
+ this.dragStatus = StageDragStatus.END;
328
387
  const frame = this.moveableHelper?.getFrame(e.target);
329
388
  this.emit('update', {
330
389
  el: this.target,
@@ -340,18 +399,18 @@ export default class StageDragResize extends EventEmitter {
340
399
 
341
400
  this.moveable
342
401
  .on('scaleStart', (e) => {
343
- this.dragStatus = ActionStatus.START;
402
+ this.dragStatus = StageDragStatus.START;
344
403
  this.moveableHelper?.onScaleStart(e);
345
404
  })
346
405
  .on('scale', (e) => {
347
406
  if (!this.target || !this.dragEl) return;
348
- this.dragStatus = ActionStatus.ING;
407
+ this.dragStatus = StageDragStatus.ING;
349
408
  this.moveableHelper?.onScale(e);
350
409
  const frame = this.moveableHelper?.getFrame(e.target);
351
410
  this.target.style.transform = frame?.toCSSObject().transform || '';
352
411
  })
353
412
  .on('scaleEnd', (e) => {
354
- this.dragStatus = ActionStatus.END;
413
+ this.dragStatus = StageDragStatus.END;
355
414
  const frame = this.moveableHelper?.getFrame(e.target);
356
415
  this.emit('update', {
357
416
  el: this.target,
@@ -381,20 +440,41 @@ export default class StageDragResize extends EventEmitter {
381
440
  }
382
441
  }
383
442
 
384
- private update(isResize = false): void {
443
+ private update(isResize = false, parentEl: HTMLElement | null = null): void {
385
444
  if (!this.target) return;
386
445
 
446
+ const { contentWindow } = this.core.renderer;
447
+ const doc = contentWindow?.document;
448
+
449
+ if (!doc) return;
450
+
387
451
  const offset =
388
452
  this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
389
453
 
390
- const left = this.calcValueByFontsize(offset.left);
391
- const top = this.calcValueByFontsize(offset.top);
392
- const width = this.calcValueByFontsize(this.target.clientWidth);
393
- const height = this.calcValueByFontsize(this.target.clientHeight);
454
+ let left = calcValueByFontsize(doc, offset.left);
455
+ let top = calcValueByFontsize(doc, offset.top);
456
+ const width = calcValueByFontsize(doc, this.target.clientWidth);
457
+ const height = calcValueByFontsize(doc, this.target.clientHeight);
458
+
459
+ if (parentEl && this.mode === Mode.ABSOLUTE && this.dragEl) {
460
+ const [translateX, translateY] = this.moveableHelper?.getFrame(this.dragEl).properties.transform.translate.value;
461
+ const { left: parentLeft, top: parentTop } = getOffset(parentEl);
462
+ left =
463
+ calcValueByFontsize(doc, this.dragEl.offsetLeft) +
464
+ parseFloat(translateX) -
465
+ calcValueByFontsize(doc, parentLeft);
466
+ top =
467
+ calcValueByFontsize(doc, this.dragEl.offsetTop) + parseFloat(translateY) - calcValueByFontsize(doc, parentTop);
468
+ }
394
469
 
395
470
  this.emit('update', {
396
- el: this.target,
397
- style: isResize ? { left, top, width, height } : { left, top },
471
+ data: [
472
+ {
473
+ el: this.target,
474
+ style: isResize ? { left, top, width, height } : { left, top },
475
+ },
476
+ ],
477
+ parentEl,
398
478
  });
399
479
  }
400
480
 
@@ -404,6 +484,7 @@ export default class StageDragResize extends EventEmitter {
404
484
  }
405
485
 
406
486
  const ghostEl = el.cloneNode(true) as HTMLElement;
487
+ this.setGhostElChildrenId(ghostEl);
407
488
  const { top, left } = getAbsolutePosition(el, getOffset(el));
408
489
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
409
490
  ghostEl.style.zIndex = ZIndex.GHOST_EL;
@@ -415,34 +496,21 @@ export default class StageDragResize extends EventEmitter {
415
496
  return ghostEl;
416
497
  }
417
498
 
418
- private destroyGhostEl(): void {
419
- this.ghostEl?.remove();
420
- this.ghostEl = undefined;
421
- }
422
-
423
- private updateDragEl(el: HTMLElement) {
424
- const offset = getOffset(el);
425
- const { transform } = getComputedStyle(el);
426
-
427
- this.dragEl.style.cssText = `
428
- position: absolute;
429
- transform: ${transform};
430
- left: ${offset.left}px;
431
- top: ${offset.top}px;
432
- width: ${el.clientWidth}px;
433
- height: ${el.clientHeight}px;
434
- z-index: ${ZIndex.DRAG_EL};
435
- `;
436
-
437
- this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
499
+ private setGhostElChildrenId(el: Element) {
500
+ for (const child of Array.from(el.children)) {
501
+ if (child.id) {
502
+ child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
503
+ }
438
504
 
439
- if (typeof this.core.config.updateDragEl === 'function') {
440
- this.core.config.updateDragEl(this.dragEl, el);
505
+ if (child.children.length) {
506
+ this.setGhostElChildrenId(child);
507
+ }
441
508
  }
442
509
  }
443
510
 
444
- private destroyDragEl(): void {
445
- this.dragEl?.remove();
511
+ private destroyGhostEl(): void {
512
+ this.ghostEl?.remove();
513
+ this.ghostEl = undefined;
446
514
  }
447
515
 
448
516
  private getOptions(options: MoveableOptions = {}): MoveableOptions {
@@ -503,7 +571,7 @@ export default class StageDragResize extends EventEmitter {
503
571
  top: 0,
504
572
  // 设置0的话无法移动到left为0,所以只能设置为-1
505
573
  left: -1,
506
- right: this.container.clientWidth,
574
+ right: this.container.clientWidth - 1,
507
575
  bottom: this.container.clientHeight,
508
576
  ...(moveableOptions.bounds || {}),
509
577
  },
@@ -512,85 +580,10 @@ export default class StageDragResize extends EventEmitter {
512
580
  };
513
581
  }
514
582
 
515
- private calcValueByFontsize(value: number) {
516
- const { contentWindow } = this.core.renderer;
517
- const fontSize = contentWindow?.document.documentElement.style.fontSize;
518
-
519
- if (fontSize) {
520
- const times = globalThis.parseFloat(fontSize) / 100;
521
- return (value / times).toFixed(2);
522
- }
523
-
524
- return value;
583
+ private canContainerHighlight() {
584
+ return (
585
+ this.core.containerHighlightType === ContainerHighlightType.DEFAULT ||
586
+ (this.core.containerHighlightType === ContainerHighlightType.ALT && this.isContainerHighlight)
587
+ );
525
588
  }
526
589
  }
527
-
528
- /**
529
- * 下移组件位置
530
- * @param {number} deltaTop 偏移量
531
- * @param {Object} detail 当前选中的组件配置
532
- */
533
- export const down = (deltaTop: number, target: HTMLElement | SVGElement): SortEventData | void => {
534
- let swapIndex = 0;
535
- let addUpH = target.clientHeight;
536
- const brothers = Array.from(target.parentNode?.children || []).filter(
537
- (node) => !node.id.startsWith(GHOST_EL_ID_PREFIX),
538
- );
539
- const index = brothers.indexOf(target);
540
- // 往下移动
541
- const downEls = brothers.slice(index + 1) as HTMLElement[];
542
-
543
- for (let i = 0; i < downEls.length; i++) {
544
- const ele = downEls[i];
545
- // 是 fixed 不做处理
546
- if (ele.style?.position === 'fixed') {
547
- continue;
548
- }
549
- addUpH += ele.clientHeight / 2;
550
- if (deltaTop <= addUpH) {
551
- break;
552
- }
553
- addUpH += ele.clientHeight / 2;
554
- swapIndex = i;
555
- }
556
- return {
557
- src: target.id,
558
- dist: downEls.length && swapIndex > -1 ? downEls[swapIndex].id : target.id,
559
- };
560
- };
561
-
562
- /**
563
- * 上移组件位置
564
- * @param {Array} brothers 处于同一容器下的所有子组件配置
565
- * @param {number} index 当前组件所处的位置
566
- * @param {number} deltaTop 偏移量
567
- * @param {Object} detail 当前选中的组件配置
568
- */
569
- export const up = (deltaTop: number, target: HTMLElement | SVGElement): SortEventData | void => {
570
- const brothers = Array.from(target.parentNode?.children || []).filter(
571
- (node) => !node.id.startsWith(GHOST_EL_ID_PREFIX),
572
- );
573
- const index = brothers.indexOf(target);
574
- // 往上移动
575
- const upEls = brothers.slice(0, index) as HTMLElement[];
576
-
577
- let addUpH = target.clientHeight;
578
- let swapIndex = upEls.length - 1;
579
-
580
- for (let i = upEls.length - 1; i >= 0; i--) {
581
- const ele = upEls[i];
582
- if (!ele) continue;
583
- // 是 fixed 不做处理
584
- if (ele.style.position === 'fixed') continue;
585
-
586
- addUpH += ele.clientHeight / 2;
587
- if (-deltaTop <= addUpH) break;
588
- addUpH += ele.clientHeight / 2;
589
-
590
- swapIndex = i;
591
- }
592
- return {
593
- src: target.id,
594
- dist: upEls.length && swapIndex > -1 ? upEls[swapIndex].id : target.id,
595
- };
596
- };
@@ -16,7 +16,6 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- /* eslint-disable no-param-reassign */
20
19
  import { EventEmitter } from 'events';
21
20
 
22
21
  import Moveable from 'moveable';
@@ -58,7 +57,7 @@ export default class StageHighlight extends EventEmitter {
58
57
  target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
59
58
  origin: false,
60
59
  rootContainer: this.core.container,
61
- zoom: 1,
60
+ zoom: 2,
62
61
  });
63
62
  }
64
63
 
package/src/StageMask.ts CHANGED
@@ -16,23 +16,22 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ import KeyController from 'keycon';
19
20
  import { throttle } from 'lodash-es';
20
21
 
22
+ import { createDiv, injectStyle } from '@tmagic/utils';
23
+
21
24
  import { Mode, MouseButton, ZIndex } from './const';
22
25
  import Rule from './Rule';
23
26
  import type StageCore from './StageCore';
24
27
  import type { StageMaskConfig } from './types';
25
- import { createDiv, getScrollParent, isFixedParent } from './util';
28
+ import { getScrollParent, isFixedParent } from './util';
26
29
 
27
30
  const wrapperClassName = 'editor-mask-wrapper';
28
31
  const throttleTime = 100;
29
32
 
30
33
  const hideScrollbar = () => {
31
- const style = globalThis.document.createElement('style');
32
- style.innerHTML = `
33
- .${wrapperClassName}::-webkit-scrollbar { width: 0 !important; display: none }
34
- `;
35
- globalThis.document.head.appendChild(style);
34
+ injectStyle(globalThis.document, `.${wrapperClassName}::-webkit-scrollbar { width: 0 !important; display: none }`);
36
35
  };
37
36
 
38
37
  const createContent = (): HTMLDivElement =>
@@ -84,6 +83,7 @@ export default class StageMask extends Rule {
84
83
  public maxScrollTop = 0;
85
84
  public maxScrollLeft = 0;
86
85
  public intersectionObserver: IntersectionObserver | null = null;
86
+ public isMultiSelectStatus: Boolean = false;
87
87
 
88
88
  private mode: Mode = Mode.ABSOLUTE;
89
89
  private pageResizeObserver: ResizeObserver | null = null;
@@ -108,6 +108,19 @@ export default class StageMask extends Rule {
108
108
  this.content.addEventListener('wheel', this.mouseWheelHandler);
109
109
  this.content.addEventListener('mousemove', this.highlightHandler);
110
110
  this.content.addEventListener('mouseleave', this.mouseLeaveHandler);
111
+
112
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
113
+
114
+ const ctrl = isMac ? 'meta' : 'ctrl';
115
+
116
+ KeyController.global.keydown(ctrl, (e) => {
117
+ e.inputEvent.preventDefault();
118
+ this.isMultiSelectStatus = true;
119
+ });
120
+ KeyController.global.keyup(ctrl, (e) => {
121
+ e.inputEvent.preventDefault();
122
+ this.isMultiSelectStatus = false;
123
+ });
111
124
  }
112
125
 
113
126
  public setMode(mode: Mode) {
@@ -294,21 +307,28 @@ export default class StageMask extends Rule {
294
307
  */
295
308
  private mouseDownHandler = (event: MouseEvent): void => {
296
309
  this.emit('clearHighlight');
297
-
298
310
  event.stopImmediatePropagation();
299
311
  event.stopPropagation();
300
312
 
301
313
  if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT) return;
302
314
 
303
- // 点击的对象如果是选中框,则不需要再触发选中了,而可能是拖动行为
315
+ // 如果单击多选选中区域,则不需要再触发选中了,而可能是拖动行为
316
+ if (!this.isMultiSelectStatus && (event.target as HTMLDivElement).className.indexOf('moveable-area') !== -1) {
317
+ return;
318
+ }
319
+ // 点击对象如果是边框锚点,则可能是resize
304
320
  if ((event.target as HTMLDivElement).className.indexOf('moveable-control') !== -1) {
305
321
  return;
306
322
  }
307
323
 
308
324
  this.content.removeEventListener('mousemove', this.highlightHandler);
309
325
 
310
- this.emit('beforeSelect', event);
311
-
326
+ // 判断触发多选还是单选
327
+ if (this.isMultiSelectStatus) {
328
+ this.emit('beforeMultiSelect', event);
329
+ } else {
330
+ this.emit('beforeSelect', event);
331
+ }
312
332
  // 如果是右键点击,这里的mouseup事件监听没有效果
313
333
  globalThis.document.addEventListener('mouseup', this.mouseUpHandler);
314
334
  };
@@ -316,7 +336,9 @@ export default class StageMask extends Rule {
316
336
  private mouseUpHandler = (): void => {
317
337
  globalThis.document.removeEventListener('mouseup', this.mouseUpHandler);
318
338
  this.content.addEventListener('mousemove', this.highlightHandler);
319
- this.emit('select');
339
+ if (!this.isMultiSelectStatus) {
340
+ this.emit('select');
341
+ }
320
342
  };
321
343
 
322
344
  private mouseWheelHandler = (event: WheelEvent) => {