@tmagic/stage 1.0.0-rc.6 → 1.0.0-rc.9

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.0-rc.6",
2
+ "version": "1.0.0-rc.9",
3
3
  "name": "@tmagic/stage",
4
4
  "sideEffects": [
5
5
  "dist/*"
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@scena/guides": "^0.17.0",
30
- "@tmagic/core": "^1.0.0-rc.6",
31
- "@tmagic/schema": "^1.0.0-rc.6",
32
- "@tmagic/utils": "^1.0.0-rc.6",
30
+ "@tmagic/core": "1.0.0-rc.9",
31
+ "@tmagic/schema": "1.0.0-rc.9",
32
+ "@tmagic/utils": "1.0.0-rc.9",
33
33
  "events": "^3.3.0",
34
34
  "lodash-es": "^4.17.21",
35
35
  "moveable": "^0.29.4",
@@ -43,6 +43,5 @@
43
43
  "typescript": "^4.3.4",
44
44
  "vite": "^2.3.7",
45
45
  "vite-plugin-dts": "^0.9.6"
46
- },
47
- "gitHead": "a93928e56d73b7924991e899a4dfaf9614cd357c"
46
+ }
48
47
  }
@@ -25,7 +25,7 @@ import MoveableHelper from 'moveable-helper';
25
25
 
26
26
  import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
27
27
  import StageCore from './StageCore';
28
- import type { Offset, SortEventData, StageDragResizeConfig } from './types';
28
+ import type { SortEventData, StageDragResizeConfig } from './types';
29
29
  import { getAbsolutePosition, getGuideLineFromCache, getMode, getOffset } from './util';
30
30
 
31
31
  /** 拖动状态 */
@@ -48,7 +48,7 @@ export default class StageDragResize extends EventEmitter {
48
48
  /** 目标节点 */
49
49
  public target?: HTMLElement;
50
50
  /** 目标节点在蒙层中的占位节点 */
51
- public dragEl: HTMLElement;
51
+ public dragEl: HTMLDivElement;
52
52
  /** Moveable拖拽类实例 */
53
53
  public moveable?: Moveable;
54
54
  /** 水平参考线 */
@@ -87,10 +87,9 @@ export default class StageDragResize extends EventEmitter {
87
87
  const oldTarget = this.target;
88
88
  this.target = el;
89
89
 
90
- this.init(el);
91
-
92
90
  // 从不能拖动到能拖动的节点之间切换,要重新创建moveable,不然dragStart不生效
93
91
  if (!this.moveable || this.target !== oldTarget) {
92
+ this.init(el);
94
93
  this.moveableHelper = MoveableHelper.create({
95
94
  useBeforeRender: true,
96
95
  useRender: false,
@@ -203,49 +202,47 @@ export default class StageDragResize extends EventEmitter {
203
202
 
204
203
  this.bindResizeEvent();
205
204
  this.bindDragEvent();
205
+ this.bindRotateEvent();
206
+ this.bindScaleEvent();
206
207
  }
207
208
 
208
209
  private bindResizeEvent(): void {
209
210
  if (!this.moveable) throw new Error('moveable 为初始化');
210
211
 
211
212
  const frame = {
212
- translate: [0, 0],
213
+ left: 0,
214
+ top: 0,
213
215
  };
214
216
 
215
217
  this.moveable
216
218
  .on('resizeStart', (e) => {
217
- if (e.dragStart) {
218
- const rect = this.moveable!.getRect();
219
- const offset = getAbsolutePosition(e.target as HTMLElement, rect);
220
- e.dragStart.set([offset.left, offset.top]);
221
- }
219
+ if (!this.target) return;
220
+
221
+ this.dragStatus = ActionStatus.START;
222
+ this.moveableHelper?.onResizeStart(e);
223
+
224
+ frame.top = this.target.offsetTop;
225
+ frame.left = this.target.offsetLeft;
222
226
  })
223
- .on('resize', ({ width, height, drag }) => {
227
+ .on('resize', (e) => {
228
+ const { width, height, drag } = e;
224
229
  if (!this.moveable || !this.target || !this.dragEl) return;
225
230
 
226
231
  const { beforeTranslate } = drag;
227
- frame.translate = beforeTranslate;
228
232
  this.dragStatus = ActionStatus.ING;
229
233
 
230
- this.target.style.width = `${width}px`;
231
- this.target.style.height = `${height}px`;
232
- this.dragEl.style.width = `${width}px`;
233
- this.dragEl.style.height = `${height}px`;
234
+ this.moveableHelper?.onResize(e);
234
235
 
235
236
  // 流式布局
236
237
  if (this.mode === Mode.SORTABLE) {
237
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
238
- this.target.style.top = `0px`;
239
- return;
238
+ this.target.style.top = '0px';
239
+ } else {
240
+ this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
241
+ this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
240
242
  }
241
243
 
242
- this.dragEl.style.left = `${beforeTranslate[0]}px`;
243
- this.dragEl.style.top = `${beforeTranslate[1]}px`;
244
-
245
- const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
246
-
247
- this.target.style.left = `${offset.left}px`;
248
- this.target.style.top = `${offset.top}px`;
244
+ this.target.style.width = `${width}px`;
245
+ this.target.style.height = `${height}px`;
249
246
  })
250
247
  .on('resizeEnd', () => {
251
248
  this.dragStatus = ActionStatus.END;
@@ -256,7 +253,10 @@ export default class StageDragResize extends EventEmitter {
256
253
  private bindDragEvent(): void {
257
254
  if (!this.moveable) throw new Error('moveable 为初始化');
258
255
 
259
- let offset: Offset | null = null;
256
+ const frame = {
257
+ left: 0,
258
+ top: 0,
259
+ };
260
260
 
261
261
  this.moveable
262
262
  .on('dragStart', (e) => {
@@ -269,29 +269,25 @@ export default class StageDragResize extends EventEmitter {
269
269
  if (this.mode === Mode.SORTABLE) {
270
270
  this.ghostEl = this.generateGhostEl(this.target);
271
271
  }
272
+
273
+ frame.top = this.target.offsetTop;
274
+ frame.left = this.target.offsetLeft;
272
275
  })
273
276
  .on('drag', (e) => {
274
277
  if (!this.target || !this.dragEl) return;
275
278
 
276
- if (!offset) {
277
- offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
278
- }
279
-
280
279
  this.dragStatus = ActionStatus.ING;
281
280
 
282
- const { left, top } = e;
283
-
284
281
  // 流式布局
285
282
  if (this.ghostEl) {
286
- this.dragEl.style.top = `${top}px`;
287
- this.ghostEl.style.top = `${top + offset.top}px`;
283
+ this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
288
284
  return;
289
285
  }
290
286
 
291
287
  this.moveableHelper?.onDrag(e);
292
288
 
293
- this.target.style.left = `${left + offset.left}px`;
294
- this.target.style.top = `${top + offset.top}px`;
289
+ this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
290
+ this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
295
291
  })
296
292
  .on('dragEnd', () => {
297
293
  // 点击不拖动时会触发dragStart和dragEnd,但是不会有drag事件
@@ -304,13 +300,66 @@ export default class StageDragResize extends EventEmitter {
304
300
  this.update();
305
301
  }
306
302
  }
307
- offset = null;
308
303
 
309
304
  this.dragStatus = ActionStatus.END;
310
305
  this.destroyGhostEl();
311
306
  });
312
307
  }
313
308
 
309
+ private bindRotateEvent(): void {
310
+ if (!this.moveable) throw new Error('moveable 为初始化');
311
+
312
+ this.moveable
313
+ .on('rotateStart', (e) => {
314
+ this.dragStatus = ActionStatus.START;
315
+ this.moveableHelper?.onRotateStart(e);
316
+ })
317
+ .on('rotate', (e) => {
318
+ if (!this.target || !this.dragEl) return;
319
+ this.dragStatus = ActionStatus.ING;
320
+ this.moveableHelper?.onRotate(e);
321
+ const frame = this.moveableHelper?.getFrame(e.target);
322
+ this.target.style.transform = frame?.toCSSObject().transform || '';
323
+ })
324
+ .on('rotateEnd', (e) => {
325
+ this.dragStatus = ActionStatus.END;
326
+ const frame = this.moveableHelper?.getFrame(e.target);
327
+ this.emit('update', {
328
+ el: this.target,
329
+ style: {
330
+ transform: frame?.get('transform'),
331
+ },
332
+ });
333
+ });
334
+ }
335
+
336
+ private bindScaleEvent(): void {
337
+ if (!this.moveable) throw new Error('moveable 为初始化');
338
+
339
+ this.moveable
340
+ .on('scaleStart', (e) => {
341
+ this.dragStatus = ActionStatus.START;
342
+ this.moveableHelper?.onScaleStart(e);
343
+ })
344
+ .on('scale', (e) => {
345
+ if (!this.target || !this.dragEl) return;
346
+ this.dragStatus = ActionStatus.ING;
347
+ this.moveableHelper?.onScale(e);
348
+ const frame = this.moveableHelper?.getFrame(e.target);
349
+ this.target.style.transform = frame?.toCSSObject().transform || '';
350
+ })
351
+ .on('scaleEnd', (e) => {
352
+ this.dragStatus = ActionStatus.END;
353
+ const frame = this.moveableHelper?.getFrame(e.target);
354
+ this.emit('update', {
355
+ el: this.target,
356
+ style: {
357
+ transform: frame?.get('transform'),
358
+ },
359
+ });
360
+ });
361
+ }
362
+
314
363
  private sort(): void {
315
364
  if (!this.target || !this.ghostEl) throw new Error('未知错误');
316
365
  const { top } = this.ghostEl.getBoundingClientRect();
@@ -331,14 +380,15 @@ export default class StageDragResize extends EventEmitter {
331
380
  }
332
381
 
333
382
  private update(isResize = false): void {
334
- const rect = this.moveable!.getRect();
383
+ if (!this.target) return;
384
+
335
385
  const offset =
336
- this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : getAbsolutePosition(this.target as HTMLElement, rect);
386
+ this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
337
387
 
338
388
  const left = this.calcValueByFontsize(offset.left);
339
389
  const top = this.calcValueByFontsize(offset.top);
340
- const width = this.calcValueByFontsize(rect.width);
341
- const height = this.calcValueByFontsize(rect.height);
390
+ const width = this.calcValueByFontsize(this.target.clientWidth);
391
+ const height = this.calcValueByFontsize(this.target.clientHeight);
342
392
 
343
393
  this.emit('update', {
344
394
  el: this.target,
@@ -369,19 +419,24 @@ export default class StageDragResize extends EventEmitter {
369
419
  }
370
420
 
371
421
  private updateDragEl(el: HTMLElement) {
372
- const { width, height } = el.getBoundingClientRect();
373
422
  const offset = getOffset(el);
423
+ const { transform } = getComputedStyle(el);
374
424
 
375
425
  this.dragEl.style.cssText = `
376
426
  position: absolute;
427
+ transform: ${transform};
377
428
  left: ${offset.left}px;
378
429
  top: ${offset.top}px;
379
- width: ${width}px;
380
- height: ${height}px;
430
+ width: ${el.clientWidth}px;
431
+ height: ${el.clientHeight}px;
381
432
  z-index: ${ZIndex.DRAG_EL};
382
433
  `;
383
434
 
384
435
  this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
436
+
437
+ if (typeof this.core.config.updateDragEl === 'function') {
438
+ this.core.config.updateDragEl(this.dragEl, el);
439
+ }
385
440
  }
386
441
 
387
442
  private destroyDragEl(): void {
@@ -415,6 +470,8 @@ export default class StageDragResize extends EventEmitter {
415
470
  dragArea: false,
416
471
  draggable: true,
417
472
  resizable: true,
473
+ scalable: false,
474
+ rotatable: false,
418
475
  snappable: isAbsolute || isFixed,
419
476
  snapGap: isAbsolute || isFixed,
420
477
  snapThreshold: 5,
@@ -41,6 +41,7 @@ export default class StageHighlight extends EventEmitter {
41
41
  parent: this.core.mask.content,
42
42
  mask: this.core.mask,
43
43
  dr: this.core.dr,
44
+ core: this.core,
44
45
  });
45
46
  }
46
47
 
@@ -20,6 +20,7 @@
20
20
  import { EventEmitter } from 'events';
21
21
 
22
22
  import { Mode } from './const';
23
+ import StageCore from './StageCore';
23
24
  import StageDragResize from './StageDragResize';
24
25
  import StageMask from './StageMask';
25
26
  import type { Offset, TargetCalibrateConfig } from './types';
@@ -32,7 +33,8 @@ export default class TargetCalibrate extends EventEmitter {
32
33
  public parent: HTMLElement;
33
34
  public mask: StageMask;
34
35
  public dr: StageDragResize;
35
- public operationEl: HTMLElement;
36
+ public core: StageCore;
37
+ public operationEl: HTMLDivElement;
36
38
 
37
39
  constructor(config: TargetCalibrateConfig) {
38
40
  super();
@@ -40,23 +42,30 @@ export default class TargetCalibrate extends EventEmitter {
40
42
  this.parent = config.parent;
41
43
  this.mask = config.mask;
42
44
  this.dr = config.dr;
45
+ this.core = config.core;
43
46
 
44
47
  this.operationEl = globalThis.document.createElement('div');
45
48
  this.parent.append(this.operationEl);
46
49
  }
47
50
 
48
51
  public update(el: HTMLElement, prefix: String): HTMLElement {
49
- const { width, height } = el.getBoundingClientRect();
50
52
  const { left, top } = this.getOffset(el);
53
+ const { transform } = getComputedStyle(el);
51
54
  this.operationEl.style.cssText = `
52
55
  position: absolute;
56
+ transform: ${transform};
53
57
  left: ${left}px;
54
58
  top: ${top}px;
55
- width: ${width}px;
56
- height: ${height}px;
59
+ width: ${el.clientWidth}px;
60
+ height: ${el.clientHeight}px;
57
61
  `;
58
62
 
59
63
  this.operationEl.id = `${prefix}${el.id}`;
64
+
65
+ if (typeof this.core.config.updateDragEl === 'function') {
66
+ this.core.config.updateDragEl(this.operationEl, el);
67
+ }
68
+
60
69
  return this.operationEl;
61
70
  }
62
71
 
@@ -65,35 +74,10 @@ export default class TargetCalibrate extends EventEmitter {
65
74
  }
66
75
 
67
76
  private getOffset(el: HTMLElement): Offset {
68
- const { transform } = getComputedStyle(el);
69
77
  const { offsetParent } = el;
70
78
 
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
- }
79
+ const left = el.offsetLeft;
80
+ const top = el.offsetTop;
97
81
 
98
82
  if (offsetParent) {
99
83
  const parentOffset = this.getOffset(offsetParent as HTMLElement);
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';
@@ -39,6 +39,7 @@ export type StageCoreConfig = {
39
39
  runtimeUrl?: string;
40
40
  render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
41
41
  autoScrollIntoView?: boolean;
42
+ updateDragEl?: (el: HTMLDivElement, target: HTMLElement) => void;
42
43
  };
43
44
 
44
45
  export interface StageRenderConfig {
@@ -58,6 +59,7 @@ export type Rect = {
58
59
  width: number;
59
60
  height: number;
60
61
  } & Offset;
62
+
61
63
  export interface Offset {
62
64
  left: number;
63
65
  top: number;
@@ -72,10 +74,14 @@ export interface UpdateEventData {
72
74
  el: HTMLElement;
73
75
  ghostEl: HTMLElement;
74
76
  style: {
75
- width: number;
76
- height: number;
77
+ width?: number;
78
+ height?: number;
77
79
  left?: number;
78
80
  top?: number;
81
+ transform?: {
82
+ rotate?: string;
83
+ scale?: string;
84
+ };
79
85
  };
80
86
  }
81
87
 
@@ -128,4 +134,5 @@ export interface TargetCalibrateConfig {
128
134
  parent: HTMLElement;
129
135
  mask: StageMask;
130
136
  dr: StageDragResize;
137
+ core: StageCore;
131
138
  }
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);