@tmagic/stage 1.0.0-rc.4 → 1.0.0-rc.7

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.
@@ -23,7 +23,7 @@ import type { MoveableOptions } from 'moveable';
23
23
  import Moveable from 'moveable';
24
24
  import MoveableHelper from 'moveable-helper';
25
25
 
26
- import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode } from './const';
26
+ import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
27
27
  import StageCore from './StageCore';
28
28
  import type { Offset, SortEventData, StageDragResizeConfig } from './types';
29
29
  import { getAbsolutePosition, getGuideLineFromCache, getMode, getOffset } from './util';
@@ -166,16 +166,12 @@ export default class StageDragResize extends EventEmitter {
166
166
 
167
167
  this.updateDragEl(el);
168
168
 
169
- this.setElementGuidelines(el);
170
-
171
169
  this.moveableOptions = this.getOptions({
172
170
  target: this.dragEl,
173
171
  });
174
172
  }
175
173
 
176
- private setElementGuidelines(el: HTMLElement) {
177
- const nodes = el.parentElement?.children || [];
178
-
174
+ private setElementGuidelines(nodes: HTMLElement[]) {
179
175
  this.elementGuidelines.forEach((node) => {
180
176
  node.remove();
181
177
  });
@@ -186,7 +182,7 @@ export default class StageDragResize extends EventEmitter {
186
182
 
187
183
  for (const node of nodes) {
188
184
  const { width, height } = node.getBoundingClientRect();
189
- if (node === el) continue;
185
+ if (node === this.target) continue;
190
186
  const { left, top } = getOffset(node as HTMLElement);
191
187
  const elementGuideline = document.createElement('div');
192
188
  elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
@@ -207,49 +203,41 @@ export default class StageDragResize extends EventEmitter {
207
203
 
208
204
  this.bindResizeEvent();
209
205
  this.bindDragEvent();
206
+ this.bindRotateEvent();
207
+ this.bindScaleEvent();
210
208
  }
211
209
 
212
210
  private bindResizeEvent(): void {
213
211
  if (!this.moveable) throw new Error('moveable 为初始化');
214
212
 
215
213
  const frame = {
216
- translate: [0, 0],
214
+ left: 0,
215
+ top: 0,
217
216
  };
218
217
 
219
218
  this.moveable
220
219
  .on('resizeStart', (e) => {
221
- if (e.dragStart) {
222
- const rect = this.moveable!.getRect();
223
- const offset = getAbsolutePosition(e.target as HTMLElement, rect);
224
- e.dragStart.set([offset.left, offset.top]);
225
- }
220
+ if (!this.target) return;
221
+
222
+ this.dragStatus = ActionStatus.START;
223
+ this.moveableHelper?.onResizeStart(e);
224
+
225
+ frame.top = this.target.offsetTop;
226
+ frame.left = this.target.offsetLeft;
226
227
  })
227
- .on('resize', ({ width, height, drag }) => {
228
+ .on('resize', (e) => {
229
+ const { width, height, drag } = e;
228
230
  if (!this.moveable || !this.target || !this.dragEl) return;
229
231
 
230
232
  const { beforeTranslate } = drag;
231
- frame.translate = beforeTranslate;
232
233
  this.dragStatus = ActionStatus.ING;
233
234
 
235
+ this.moveableHelper?.onResize(e);
236
+
234
237
  this.target.style.width = `${width}px`;
235
238
  this.target.style.height = `${height}px`;
236
- this.dragEl.style.width = `${width}px`;
237
- this.dragEl.style.height = `${height}px`;
238
-
239
- // 流式布局
240
- if (this.mode === Mode.SORTABLE) {
241
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
242
- this.target.style.top = `0px`;
243
- return;
244
- }
245
-
246
- this.dragEl.style.left = `${beforeTranslate[0]}px`;
247
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
248
-
249
- const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
250
-
251
- this.target.style.left = `${offset.left}px`;
252
- this.target.style.top = `${offset.top}px`;
239
+ this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
240
+ this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
253
241
  })
254
242
  .on('resizeEnd', () => {
255
243
  this.dragStatus = ActionStatus.END;
@@ -315,6 +303,60 @@ export default class StageDragResize extends EventEmitter {
315
303
  });
316
304
  }
317
305
 
306
+ private bindRotateEvent(): void {
307
+ if (!this.moveable) throw new Error('moveable 为初始化');
308
+
309
+ this.moveable
310
+ .on('rotateStart', (e) => {
311
+ this.dragStatus = ActionStatus.START;
312
+ this.moveableHelper?.onRotateStart(e);
313
+ })
314
+ .on('rotate', (e) => {
315
+ if (!this.target || !this.dragEl) return;
316
+ this.dragStatus = ActionStatus.ING;
317
+ this.moveableHelper?.onRotate(e);
318
+ const frame = this.moveableHelper?.getFrame(e.target);
319
+ this.target.style.transform = frame?.toCSSObject().transform || '';
320
+ })
321
+ .on('rotateEnd', (e) => {
322
+ this.dragStatus = ActionStatus.END;
323
+ const frame = this.moveableHelper?.getFrame(e.target);
324
+ this.emit('update', {
325
+ el: this.target,
326
+ style: {
327
+ transform: frame?.get('transform'),
328
+ },
329
+ });
330
+ });
331
+ }
332
+
333
+ private bindScaleEvent(): void {
334
+ if (!this.moveable) throw new Error('moveable 为初始化');
335
+
336
+ this.moveable
337
+ .on('scaleStart', (e) => {
338
+ this.dragStatus = ActionStatus.START;
339
+ this.moveableHelper?.onScaleStart(e);
340
+ })
341
+ .on('scale', (e) => {
342
+ if (!this.target || !this.dragEl) return;
343
+ this.dragStatus = ActionStatus.ING;
344
+ this.moveableHelper?.onScale(e);
345
+ const frame = this.moveableHelper?.getFrame(e.target);
346
+ this.target.style.transform = frame?.toCSSObject().transform || '';
347
+ })
348
+ .on('scaleEnd', (e) => {
349
+ this.dragStatus = ActionStatus.END;
350
+ const frame = this.moveableHelper?.getFrame(e.target);
351
+ this.emit('update', {
352
+ el: this.target,
353
+ style: {
354
+ transform: frame?.get('transform'),
355
+ },
356
+ });
357
+ });
358
+ }
359
+
318
360
  private sort(): void {
319
361
  if (!this.target || !this.ghostEl) throw new Error('未知错误');
320
362
  const { top } = this.ghostEl.getBoundingClientRect();
@@ -335,14 +377,15 @@ export default class StageDragResize extends EventEmitter {
335
377
  }
336
378
 
337
379
  private update(isResize = false): void {
338
- const rect = this.moveable!.getRect();
380
+ if (!this.target) return;
381
+
339
382
  const offset =
340
- this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : getAbsolutePosition(this.target as HTMLElement, rect);
383
+ this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
341
384
 
342
385
  const left = this.calcValueByFontsize(offset.left);
343
386
  const top = this.calcValueByFontsize(offset.top);
344
- const width = this.calcValueByFontsize(rect.width);
345
- const height = this.calcValueByFontsize(rect.height);
387
+ const width = this.calcValueByFontsize(this.target.clientWidth);
388
+ const height = this.calcValueByFontsize(this.target.clientHeight);
346
389
 
347
390
  this.emit('update', {
348
391
  el: this.target,
@@ -358,7 +401,7 @@ export default class StageDragResize extends EventEmitter {
358
401
  const ghostEl = el.cloneNode(true) as HTMLElement;
359
402
  const { top, left } = getAbsolutePosition(el, getOffset(el));
360
403
  ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
361
- ghostEl.style.zIndex = '5';
404
+ ghostEl.style.zIndex = ZIndex.GHOST_EL;
362
405
  ghostEl.style.opacity = '.5';
363
406
  ghostEl.style.position = 'absolute';
364
407
  ghostEl.style.left = `${left}px`;
@@ -373,16 +416,17 @@ export default class StageDragResize extends EventEmitter {
373
416
  }
374
417
 
375
418
  private updateDragEl(el: HTMLElement) {
376
- const { width, height } = el.getBoundingClientRect();
377
419
  const offset = getOffset(el);
420
+ const { transform } = getComputedStyle(el);
378
421
 
379
422
  this.dragEl.style.cssText = `
380
423
  position: absolute;
424
+ transform: ${transform};
381
425
  left: ${offset.left}px;
382
426
  top: ${offset.top}px;
383
- width: ${width}px;
384
- height: ${height}px;
385
- z-index: 9;
427
+ width: ${el.clientWidth}px;
428
+ height: ${el.clientHeight}px;
429
+ z-index: ${ZIndex.DRAG_EL};
386
430
  `;
387
431
 
388
432
  this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
@@ -404,6 +448,14 @@ export default class StageDragResize extends EventEmitter {
404
448
  moveableOptions = moveableOptions(this.core);
405
449
  }
406
450
 
451
+ const elementGuidelines: any = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
452
+
453
+ this.setElementGuidelines(elementGuidelines);
454
+
455
+ if (moveableOptions.elementGuidelines) {
456
+ delete moveableOptions.elementGuidelines;
457
+ }
458
+
407
459
  return {
408
460
  origin: false,
409
461
  rootContainer: this.core.container,
@@ -411,6 +463,8 @@ export default class StageDragResize extends EventEmitter {
411
463
  dragArea: false,
412
464
  draggable: true,
413
465
  resizable: true,
466
+ scalable: false,
467
+ rotatable: false,
414
468
  snappable: isAbsolute || isFixed,
415
469
  snapGap: isAbsolute || isFixed,
416
470
  snapThreshold: 5,
@@ -18,7 +18,6 @@
18
18
 
19
19
  import { EventEmitter } from 'events';
20
20
 
21
- import { SELECTED_CLASS, ZIndex } from './const';
22
21
  import StageCore from './StageCore';
23
22
  import type { Runtime, RuntimeWindow, StageRenderConfig } from './types';
24
23
  import { getHost, isSameDomain } from './util';
@@ -122,16 +121,5 @@ export default class StageRender extends EventEmitter {
122
121
  this.iframe?.contentDocument?.body?.appendChild(el);
123
122
  }
124
123
  }
125
-
126
- if (this.contentWindow) {
127
- const style = this.contentWindow.document.createElement('style');
128
- style.id = 'tmagic-stage-render';
129
- style.innerHTML = `
130
- .${SELECTED_CLASS}, .${SELECTED_CLASS}-parent {
131
- z-index: ${ZIndex.SELECTED_EL};
132
- }
133
- `;
134
- this.contentWindow.document.head.appendChild(style);
135
- }
136
124
  };
137
125
  }
@@ -46,14 +46,15 @@ export default class TargetCalibrate extends EventEmitter {
46
46
  }
47
47
 
48
48
  public update(el: HTMLElement, prefix: String): HTMLElement {
49
- const { width, height } = el.getBoundingClientRect();
50
49
  const { left, top } = this.getOffset(el);
50
+ const { transform } = getComputedStyle(el);
51
51
  this.operationEl.style.cssText = `
52
52
  position: absolute;
53
+ transform: ${transform};
53
54
  left: ${left}px;
54
55
  top: ${top}px;
55
- width: ${width}px;
56
- height: ${height}px;
56
+ width: ${el.clientWidth}px;
57
+ height: ${el.clientHeight}px;
57
58
  `;
58
59
 
59
60
  this.operationEl.id = `${prefix}${el.id}`;
@@ -65,35 +66,10 @@ export default class TargetCalibrate extends EventEmitter {
65
66
  }
66
67
 
67
68
  private getOffset(el: HTMLElement): Offset {
68
- const { transform } = getComputedStyle(el);
69
69
  const { offsetParent } = el;
70
70
 
71
- let left = el.offsetLeft;
72
- let top = el.offsetTop;
73
-
74
- if (transform.indexOf('matrix') > -1) {
75
- let a = 1;
76
- let b = 1;
77
- let c = 1;
78
- let d = 1;
79
- let e = 0;
80
- let f = 0;
81
- transform.replace(
82
- /matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/,
83
- ($0: string, $1: string, $2: string, $3: string, $4: string, $5: string, $6: string): string => {
84
- a = +$1;
85
- b = +$2;
86
- c = +$3;
87
- d = +$4;
88
- e = +$5;
89
- f = +$6;
90
- return transform;
91
- },
92
- );
93
-
94
- left = a * left + c * top + e;
95
- top = b * left + d * top + f;
96
- }
71
+ const left = el.offsetLeft;
72
+ const top = el.offsetTop;
97
73
 
98
74
  if (offsetParent) {
99
75
  const parentOffset = this.getOffset(offsetParent as HTMLElement);
package/src/const.ts CHANGED
@@ -42,6 +42,8 @@ export enum ZIndex {
42
42
  MASK = '99999',
43
43
  /** 选中的节点 */
44
44
  SELECTED_EL = '666',
45
+ GHOST_EL = '700',
46
+ DRAG_EL = '9',
45
47
  }
46
48
 
47
49
  /** 鼠标按键 */
package/src/types.ts CHANGED
@@ -16,7 +16,7 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
- import { MoveableOptions } from 'react-moveable/declaration/types';
19
+ import { MoveableOptions } from 'moveable';
20
20
 
21
21
  import Core from '@tmagic/core';
22
22
  import { Id, MApp, MNode } from '@tmagic/schema';
@@ -58,6 +58,7 @@ export type Rect = {
58
58
  width: number;
59
59
  height: number;
60
60
  } & Offset;
61
+
61
62
  export interface Offset {
62
63
  left: number;
63
64
  top: number;
@@ -72,10 +73,14 @@ export interface UpdateEventData {
72
73
  el: HTMLElement;
73
74
  ghostEl: HTMLElement;
74
75
  style: {
75
- width: number;
76
- height: number;
76
+ width?: number;
77
+ height?: number;
77
78
  left?: number;
78
79
  top?: number;
80
+ transform?: {
81
+ rotate?: string;
82
+ scale?: string;
83
+ };
79
84
  };
80
85
  }
81
86
 
package/src/util.ts CHANGED
@@ -30,35 +30,10 @@ const getParents = (el: Element, relative: Element) => {
30
30
  };
31
31
 
32
32
  export const getOffset = (el: HTMLElement): Offset => {
33
- const { transform } = getComputedStyle(el);
34
33
  const { offsetParent } = el;
35
34
 
36
- let left = el.offsetLeft;
37
- let top = el.offsetTop;
38
-
39
- if (transform.indexOf('matrix') > -1) {
40
- let a = 1;
41
- let b = 1;
42
- let c = 1;
43
- let d = 1;
44
- let e = 0;
45
- let f = 0;
46
- transform.replace(
47
- /matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/,
48
- ($0: string, $1: string, $2: string, $3: string, $4: string, $5: string, $6: string): string => {
49
- a = +$1;
50
- b = +$2;
51
- c = +$3;
52
- d = +$4;
53
- e = +$5;
54
- f = +$6;
55
- return transform;
56
- },
57
- );
58
-
59
- left = a * left + c * top + e;
60
- top = b * left + d * top + f;
61
- }
35
+ const left = el.offsetLeft;
36
+ const top = el.offsetTop;
62
37
 
63
38
  if (offsetParent) {
64
39
  const parentOffset = getOffset(offsetParent as HTMLElement);