@tmagic/stage 1.2.6 → 1.2.8
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/dist/tmagic-stage.js +164 -101
- package/dist/tmagic-stage.js.map +1 -1
- package/dist/tmagic-stage.umd.cjs +168 -104
- package/dist/tmagic-stage.umd.cjs.map +1 -1
- package/package.json +6 -6
- package/src/ActionManager.ts +32 -16
- package/src/DragResizeHelper.ts +40 -2
- package/src/MoveableActionsAble.ts +109 -0
- package/src/MoveableOptionsManager.ts +6 -6
- package/src/StageCore.ts +11 -4
- package/src/StageDragResize.ts +8 -34
- package/src/StageMultiDragResize.ts +28 -14
- package/src/types.ts +16 -2
- package/types/ActionManager.d.ts +1 -1
- package/types/DragResizeHelper.d.ts +2 -1
- package/types/{MoveableSelectParentAble.d.ts → MoveableActionsAble.d.ts} +5 -2
- package/types/MoveableOptionsManager.d.ts +1 -1
- package/types/StageCore.d.ts +2 -2
- package/types/StageDragResize.d.ts +1 -0
- package/types/StageMultiDragResize.d.ts +2 -0
- package/types/types.d.ts +14 -2
- package/src/MoveableSelectParentAble.ts +0 -76
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.2.
|
|
2
|
+
"version": "1.2.8",
|
|
3
3
|
"name": "@tmagic/stage",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"url": "https://github.com/Tencent/tmagic-editor.git"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@scena/guides": "^0.
|
|
33
|
-
"@tmagic/core": "1.2.
|
|
34
|
-
"@tmagic/schema": "1.2.
|
|
35
|
-
"@tmagic/utils": "1.2.
|
|
32
|
+
"@scena/guides": "^0.23.3",
|
|
33
|
+
"@tmagic/core": "1.2.8",
|
|
34
|
+
"@tmagic/schema": "1.2.8",
|
|
35
|
+
"@tmagic/utils": "1.2.8",
|
|
36
36
|
"events": "^3.3.0",
|
|
37
37
|
"keycon": "^1.1.2",
|
|
38
38
|
"lodash-es": "^4.17.21",
|
|
39
|
-
"moveable": "^0.
|
|
39
|
+
"moveable": "^0.43.1",
|
|
40
40
|
"moveable-helper": "^0.4.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
package/src/ActionManager.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { Id } from '@tmagic/schema';
|
|
|
25
25
|
import { addClassName, getDocument, removeClassNameByClassName } from '@tmagic/utils';
|
|
26
26
|
|
|
27
27
|
import { CONTAINER_HIGHLIGHT_CLASS_NAME, GHOST_EL_ID_PREFIX, GuidesType, MouseButton, PAGE_CLASS } from './const';
|
|
28
|
+
import DragResizeHelper from './DragResizeHelper';
|
|
28
29
|
import StageDragResize from './StageDragResize';
|
|
29
30
|
import StageHighlight from './StageHighlight';
|
|
30
31
|
import StageMultiDragResize from './StageMultiDragResize';
|
|
@@ -39,6 +40,7 @@ import {
|
|
|
39
40
|
GetTargetElement,
|
|
40
41
|
IsContainer,
|
|
41
42
|
Point,
|
|
43
|
+
RemoveEventData,
|
|
42
44
|
SelectStatus,
|
|
43
45
|
StageDragStatus,
|
|
44
46
|
UpdateEventData,
|
|
@@ -100,27 +102,30 @@ export default class ActionManager extends EventEmitter {
|
|
|
100
102
|
this.getRenderDocument = config.getRenderDocument;
|
|
101
103
|
this.isContainer = config.isContainer;
|
|
102
104
|
|
|
105
|
+
const createDrHelper = () =>
|
|
106
|
+
new DragResizeHelper({
|
|
107
|
+
container: config.container,
|
|
108
|
+
updateDragEl: config.updateDragEl,
|
|
109
|
+
});
|
|
110
|
+
|
|
103
111
|
this.dr = new StageDragResize({
|
|
104
112
|
container: config.container,
|
|
105
113
|
disabledDragStart: config.disabledDragStart,
|
|
114
|
+
moveableOptions: this.changeCallback(config.moveableOptions),
|
|
115
|
+
dragResizeHelper: createDrHelper(),
|
|
106
116
|
getRootContainer: config.getRootContainer,
|
|
107
117
|
getRenderDocument: config.getRenderDocument,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
delayedMarkContainer: (event: MouseEvent, exclude: Element[]) => {
|
|
111
|
-
if (this.canAddToContainer()) {
|
|
112
|
-
return this.delayedMarkContainer(event, exclude);
|
|
113
|
-
}
|
|
114
|
-
return undefined;
|
|
115
|
-
},
|
|
116
|
-
moveableOptions: this.changeCallback(config.moveableOptions),
|
|
118
|
+
markContainerEnd: this.markContainerEnd.bind(this),
|
|
119
|
+
delayedMarkContainer: this.delayedMarkContainer.bind(this),
|
|
117
120
|
});
|
|
118
121
|
this.multiDr = new StageMultiDragResize({
|
|
119
122
|
container: config.container,
|
|
120
123
|
multiMoveableOptions: config.multiMoveableOptions,
|
|
124
|
+
dragResizeHelper: createDrHelper(),
|
|
121
125
|
getRootContainer: config.getRootContainer,
|
|
122
126
|
getRenderDocument: config.getRenderDocument,
|
|
123
|
-
|
|
127
|
+
markContainerEnd: this.markContainerEnd.bind(this),
|
|
128
|
+
delayedMarkContainer: this.delayedMarkContainer.bind(this),
|
|
124
129
|
});
|
|
125
130
|
this.highlightLayer = new StageHighlight({
|
|
126
131
|
container: config.container,
|
|
@@ -319,10 +324,13 @@ export default class ActionManager extends EventEmitter {
|
|
|
319
324
|
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
320
325
|
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
321
326
|
*/
|
|
322
|
-
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
327
|
+
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout | undefined {
|
|
328
|
+
if (this.canAddToContainer()) {
|
|
329
|
+
return globalThis.setTimeout(() => {
|
|
330
|
+
this.addContainerHighlightClassName(event, excludeElList);
|
|
331
|
+
}, this.containerHighlightDuration);
|
|
332
|
+
}
|
|
333
|
+
return undefined;
|
|
326
334
|
}
|
|
327
335
|
|
|
328
336
|
public destroy(): void {
|
|
@@ -454,11 +462,19 @@ export default class ActionManager extends EventEmitter {
|
|
|
454
462
|
})
|
|
455
463
|
.on('select-parent', () => {
|
|
456
464
|
this.emit('select-parent');
|
|
465
|
+
})
|
|
466
|
+
.on('remove', () => {
|
|
467
|
+
const drTarget = this.dr.getTarget();
|
|
468
|
+
if (!drTarget) return;
|
|
469
|
+
const data: RemoveEventData = {
|
|
470
|
+
data: [{ el: drTarget }],
|
|
471
|
+
};
|
|
472
|
+
this.emit('remove', data);
|
|
457
473
|
});
|
|
458
474
|
|
|
459
475
|
this.multiDr
|
|
460
|
-
.on('update', (data: UpdateEventData
|
|
461
|
-
this.emit('multi-update', data
|
|
476
|
+
.on('update', (data: UpdateEventData) => {
|
|
477
|
+
this.emit('multi-update', data);
|
|
462
478
|
})
|
|
463
479
|
.on('change-to-select', async (id: Id) => {
|
|
464
480
|
// 如果还在多选状态,不触发切换到单选
|
package/src/DragResizeHelper.ts
CHANGED
|
@@ -34,8 +34,8 @@ import MoveableHelper from 'moveable-helper';
|
|
|
34
34
|
|
|
35
35
|
import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, Mode, ZIndex } from './const';
|
|
36
36
|
import TargetShadow from './TargetShadow';
|
|
37
|
-
import { DragResizeHelperConfig, TargetElement } from './types';
|
|
38
|
-
import { getAbsolutePosition, getOffset } from './util';
|
|
37
|
+
import { DragResizeHelperConfig, Rect, TargetElement } from './types';
|
|
38
|
+
import { calcValueByFontsize, getAbsolutePosition, getOffset } from './util';
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* 拖拽/改变大小等操作发生时,moveable会抛出各种状态事件,DragResizeHelper负责响应这些事件,对目标节点target和拖拽节点targetShadow进行修改;
|
|
@@ -282,6 +282,44 @@ export default class DragResizeHelper {
|
|
|
282
282
|
this.moveableHelper.onDragGroup(e);
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
public getUpdatedElRect(el: HTMLElement, parentEl: HTMLElement | null, doc: Document): Rect {
|
|
286
|
+
const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: el.offsetLeft, top: el.offsetTop };
|
|
287
|
+
|
|
288
|
+
let left = calcValueByFontsize(doc, offset.left);
|
|
289
|
+
let top = calcValueByFontsize(doc, offset.top);
|
|
290
|
+
const width = calcValueByFontsize(doc, el.clientWidth);
|
|
291
|
+
const height = calcValueByFontsize(doc, el.clientHeight);
|
|
292
|
+
|
|
293
|
+
let shadowEl = this.getShadowEl();
|
|
294
|
+
const shadowEls = this.getShadowEls();
|
|
295
|
+
|
|
296
|
+
if (shadowEls.length) {
|
|
297
|
+
shadowEl = shadowEls.find((item) => item.id.endsWith(el.id));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (parentEl && this.mode === Mode.ABSOLUTE && shadowEl) {
|
|
301
|
+
const targetShadowHtmlEl = shadowEl as HTMLElement;
|
|
302
|
+
const targetShadowElOffsetLeft = targetShadowHtmlEl.offsetLeft || 0;
|
|
303
|
+
const targetShadowElOffsetTop = targetShadowHtmlEl.offsetTop || 0;
|
|
304
|
+
|
|
305
|
+
const frame = this.getFrame(shadowEl);
|
|
306
|
+
|
|
307
|
+
const [translateX, translateY] = frame?.properties.transform.translate.value;
|
|
308
|
+
const { left: parentLeft, top: parentTop } = getOffset(parentEl);
|
|
309
|
+
|
|
310
|
+
left =
|
|
311
|
+
calcValueByFontsize(doc, targetShadowElOffsetLeft) +
|
|
312
|
+
parseFloat(translateX) -
|
|
313
|
+
calcValueByFontsize(doc, parentLeft);
|
|
314
|
+
top =
|
|
315
|
+
calcValueByFontsize(doc, targetShadowElOffsetTop) +
|
|
316
|
+
parseFloat(translateY) -
|
|
317
|
+
calcValueByFontsize(doc, parentTop);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
return { width, height, left, top };
|
|
321
|
+
}
|
|
322
|
+
|
|
285
323
|
/**
|
|
286
324
|
* 多选状态设置多个节点的快照
|
|
287
325
|
*/
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { MoveableManagerInterface, Renderer } from 'moveable';
|
|
2
|
+
|
|
3
|
+
import { AbleActionEventType } from './types';
|
|
4
|
+
|
|
5
|
+
export default (handler: (type: AbleActionEventType) => void) => ({
|
|
6
|
+
name: 'actions',
|
|
7
|
+
props: {
|
|
8
|
+
selectParent: Boolean,
|
|
9
|
+
},
|
|
10
|
+
events: {},
|
|
11
|
+
render(moveable: MoveableManagerInterface<any, any>, React: Renderer) {
|
|
12
|
+
const rect = moveable.getRect();
|
|
13
|
+
const { pos2 } = moveable.state;
|
|
14
|
+
|
|
15
|
+
// use css for able
|
|
16
|
+
const editableViewer = moveable.useCSS(
|
|
17
|
+
'div',
|
|
18
|
+
`
|
|
19
|
+
{
|
|
20
|
+
position: absolute;
|
|
21
|
+
left: 0px;
|
|
22
|
+
top: 0px;
|
|
23
|
+
will-change: transform;
|
|
24
|
+
transform-origin: 0px 0px;
|
|
25
|
+
display: flex;
|
|
26
|
+
}
|
|
27
|
+
.moveable-button {
|
|
28
|
+
width: 20px;
|
|
29
|
+
height: 20px;
|
|
30
|
+
background: #4af;
|
|
31
|
+
border-radius: 4px;
|
|
32
|
+
appearance: none;
|
|
33
|
+
border: 0;
|
|
34
|
+
color: white;
|
|
35
|
+
font-size: 12px;
|
|
36
|
+
font-weight: bold;
|
|
37
|
+
margin-left: 2px;
|
|
38
|
+
position: relative;
|
|
39
|
+
}
|
|
40
|
+
.moveable-remove-button:before, .moveable-remove-button:after {
|
|
41
|
+
content: "";
|
|
42
|
+
position: absolute;
|
|
43
|
+
left: 50%;
|
|
44
|
+
top: 50%;
|
|
45
|
+
transform: translate(-50%, -50%) rotate(45deg);
|
|
46
|
+
width: 14px;
|
|
47
|
+
height: 2px;
|
|
48
|
+
background: #fff;
|
|
49
|
+
border-radius: 1px;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
}
|
|
52
|
+
.moveable-remove-button:after {
|
|
53
|
+
transform: translate(-50%, -50%) rotate(-45deg);
|
|
54
|
+
}
|
|
55
|
+
`,
|
|
56
|
+
);
|
|
57
|
+
// Add key (required)
|
|
58
|
+
// Add class prefix moveable-(required)
|
|
59
|
+
return React.createElement(
|
|
60
|
+
editableViewer,
|
|
61
|
+
{
|
|
62
|
+
className: 'moveable-editable',
|
|
63
|
+
style: {
|
|
64
|
+
transform: `translate(${pos2[0] - 48}px, ${pos2[1] - 28}px) rotate(${rect.rotation}deg) translate(10px)`,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
[
|
|
68
|
+
React.createElement(
|
|
69
|
+
'button',
|
|
70
|
+
{
|
|
71
|
+
className: 'moveable-button',
|
|
72
|
+
title: '选中父组件',
|
|
73
|
+
onClick: () => {
|
|
74
|
+
handler(AbleActionEventType.SELECT_PARENT);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
React.createElement(
|
|
78
|
+
'svg',
|
|
79
|
+
{
|
|
80
|
+
width: '20px',
|
|
81
|
+
height: '20px',
|
|
82
|
+
viewBox: '0 0 16 16',
|
|
83
|
+
fill: 'none',
|
|
84
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
85
|
+
style: {
|
|
86
|
+
transform: 'rotate(90deg)',
|
|
87
|
+
position: 'absolute',
|
|
88
|
+
left: 0,
|
|
89
|
+
top: 0,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
React.createElement('path', {
|
|
93
|
+
d: 'M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z',
|
|
94
|
+
fill: 'currentColor',
|
|
95
|
+
fillOpacity: '0.9',
|
|
96
|
+
}),
|
|
97
|
+
),
|
|
98
|
+
),
|
|
99
|
+
React.createElement('button', {
|
|
100
|
+
className: 'moveable-button moveable-remove-button',
|
|
101
|
+
title: '删除',
|
|
102
|
+
onClick: () => {
|
|
103
|
+
handler(AbleActionEventType.REMOVE);
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
],
|
|
107
|
+
);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
@@ -22,8 +22,8 @@ import { merge } from 'lodash-es';
|
|
|
22
22
|
import { MoveableOptions } from 'moveable';
|
|
23
23
|
|
|
24
24
|
import { GuidesType, Mode } from './const';
|
|
25
|
-
import
|
|
26
|
-
import { GetRootContainer, MoveableOptionsManagerConfig } from './types';
|
|
25
|
+
import MoveableActionsAble from './MoveableActionsAble';
|
|
26
|
+
import { AbleActionEventType, GetRootContainer, MoveableOptionsManagerConfig } from './types';
|
|
27
27
|
import { getOffset } from './util';
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -173,10 +173,10 @@ export default class MoveableOptionsManager extends EventEmitter {
|
|
|
173
173
|
isDisplayInnerSnapDigit: true,
|
|
174
174
|
|
|
175
175
|
props: {
|
|
176
|
-
|
|
176
|
+
actions: true,
|
|
177
177
|
},
|
|
178
178
|
|
|
179
|
-
ables: [
|
|
179
|
+
ables: [MoveableActionsAble(this.actionHandler.bind(this))],
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
|
|
@@ -208,8 +208,8 @@ export default class MoveableOptionsManager extends EventEmitter {
|
|
|
208
208
|
/**
|
|
209
209
|
* 这是给selectParentAbles的回调函数,用于触发选中父元素事件
|
|
210
210
|
*/
|
|
211
|
-
private
|
|
212
|
-
this.emit(
|
|
211
|
+
private actionHandler(type: AbleActionEventType): void {
|
|
212
|
+
this.emit(type);
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
/**
|
package/src/StageCore.ts
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
GuidesEventData,
|
|
31
31
|
Point,
|
|
32
32
|
RemoveData,
|
|
33
|
+
RemoveEventData,
|
|
33
34
|
Runtime,
|
|
34
35
|
StageCoreConfig,
|
|
35
36
|
UpdateData,
|
|
@@ -188,7 +189,10 @@ export default class StageCore extends EventEmitter {
|
|
|
188
189
|
/**
|
|
189
190
|
* @deprecated 废弃接口,建议用delayedMarkContainer代替
|
|
190
191
|
*/
|
|
191
|
-
public getAddContainerHighlightClassNameTimeout(
|
|
192
|
+
public getAddContainerHighlightClassNameTimeout(
|
|
193
|
+
event: MouseEvent,
|
|
194
|
+
excludeElList: Element[] = [],
|
|
195
|
+
): NodeJS.Timeout | undefined {
|
|
192
196
|
return this.delayedMarkContainer(event, excludeElList);
|
|
193
197
|
}
|
|
194
198
|
|
|
@@ -199,7 +203,7 @@ export default class StageCore extends EventEmitter {
|
|
|
199
203
|
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
200
204
|
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
201
205
|
*/
|
|
202
|
-
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout {
|
|
206
|
+
public delayedMarkContainer(event: MouseEvent, excludeElList: Element[] = []): NodeJS.Timeout | undefined {
|
|
203
207
|
return this.actionManager.delayedMarkContainer(event, excludeElList);
|
|
204
208
|
}
|
|
205
209
|
|
|
@@ -313,6 +317,9 @@ export default class StageCore extends EventEmitter {
|
|
|
313
317
|
})
|
|
314
318
|
.on('select-parent', () => {
|
|
315
319
|
this.emit('select-parent');
|
|
320
|
+
})
|
|
321
|
+
.on('remove', (data: RemoveEventData) => {
|
|
322
|
+
this.emit('remove', data);
|
|
316
323
|
});
|
|
317
324
|
}
|
|
318
325
|
|
|
@@ -327,8 +334,8 @@ export default class StageCore extends EventEmitter {
|
|
|
327
334
|
// 先保证画布内完成渲染,再通知外部更新
|
|
328
335
|
setTimeout(() => this.emit('select', el));
|
|
329
336
|
})
|
|
330
|
-
.on('multi-update', (data: UpdateEventData
|
|
331
|
-
this.emit('update',
|
|
337
|
+
.on('multi-update', (data: UpdateEventData) => {
|
|
338
|
+
this.emit('update', data);
|
|
332
339
|
});
|
|
333
340
|
}
|
|
334
341
|
|
package/src/StageDragResize.ts
CHANGED
|
@@ -24,7 +24,7 @@ import DragResizeHelper from './DragResizeHelper';
|
|
|
24
24
|
import MoveableOptionsManager from './MoveableOptionsManager';
|
|
25
25
|
import type { DelayedMarkContainer, GetRenderDocument, MarkContainerEnd, StageDragResizeConfig } from './types';
|
|
26
26
|
import { StageDragStatus } from './types';
|
|
27
|
-
import {
|
|
27
|
+
import { down, getMode, up } from './util';
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* 管理单选操作,响应选中操作,初始化moveableOption参数并初始化moveable,处理moveable回调事件对组件进行更新
|
|
@@ -51,10 +51,7 @@ export default class StageDragResize extends MoveableOptionsManager {
|
|
|
51
51
|
this.delayedMarkContainer = config.delayedMarkContainer;
|
|
52
52
|
this.disabledDragStart = config.disabledDragStart;
|
|
53
53
|
|
|
54
|
-
this.dragResizeHelper =
|
|
55
|
-
container: config.container,
|
|
56
|
-
updateDragEl: config.updateDragEl,
|
|
57
|
-
});
|
|
54
|
+
this.dragResizeHelper = config.dragResizeHelper;
|
|
58
55
|
|
|
59
56
|
this.on('update-moveable', () => {
|
|
60
57
|
if (this.moveable) {
|
|
@@ -63,6 +60,10 @@ export default class StageDragResize extends MoveableOptionsManager {
|
|
|
63
60
|
});
|
|
64
61
|
}
|
|
65
62
|
|
|
63
|
+
public getTarget() {
|
|
64
|
+
return this.target;
|
|
65
|
+
}
|
|
66
|
+
|
|
66
67
|
/**
|
|
67
68
|
* 将选中框渲染并覆盖到选中的组件Dom节点上方
|
|
68
69
|
* 当选中的节点不是absolute时,会创建一个新的节点出来作为拖拽目标
|
|
@@ -311,40 +312,13 @@ export default class StageDragResize extends MoveableOptionsManager {
|
|
|
311
312
|
|
|
312
313
|
if (!doc) return;
|
|
313
314
|
|
|
314
|
-
const
|
|
315
|
-
this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
|
|
316
|
-
|
|
317
|
-
let left = calcValueByFontsize(doc, offset.left);
|
|
318
|
-
let top = calcValueByFontsize(doc, offset.top);
|
|
319
|
-
const width = calcValueByFontsize(doc, this.target.clientWidth);
|
|
320
|
-
const height = calcValueByFontsize(doc, this.target.clientHeight);
|
|
321
|
-
|
|
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;
|
|
331
|
-
const { left: parentLeft, top: parentTop } = getOffset(parentEl);
|
|
332
|
-
|
|
333
|
-
left =
|
|
334
|
-
calcValueByFontsize(doc, targetShadowElOffsetLeft) +
|
|
335
|
-
parseFloat(translateX) -
|
|
336
|
-
calcValueByFontsize(doc, parentLeft);
|
|
337
|
-
top =
|
|
338
|
-
calcValueByFontsize(doc, targetShadowElOffsetTop) +
|
|
339
|
-
parseFloat(translateY) -
|
|
340
|
-
calcValueByFontsize(doc, parentTop);
|
|
341
|
-
}
|
|
315
|
+
const rect = this.dragResizeHelper.getUpdatedElRect(this.target, parentEl, doc);
|
|
342
316
|
|
|
343
317
|
this.emit('update', {
|
|
344
318
|
data: [
|
|
345
319
|
{
|
|
346
320
|
el: this.target,
|
|
347
|
-
style: isResize ?
|
|
321
|
+
style: isResize ? rect : { left: rect.left, top: rect.top },
|
|
348
322
|
},
|
|
349
323
|
],
|
|
350
324
|
parentEl,
|
|
@@ -21,8 +21,15 @@ import Moveable from 'moveable';
|
|
|
21
21
|
import { DRAG_EL_ID_PREFIX, Mode } from './const';
|
|
22
22
|
import DragResizeHelper from './DragResizeHelper';
|
|
23
23
|
import MoveableOptionsManager from './MoveableOptionsManager';
|
|
24
|
-
import {
|
|
25
|
-
|
|
24
|
+
import {
|
|
25
|
+
DelayedMarkContainer,
|
|
26
|
+
GetRenderDocument,
|
|
27
|
+
MarkContainerEnd,
|
|
28
|
+
MoveableOptionsManagerConfig,
|
|
29
|
+
StageDragStatus,
|
|
30
|
+
StageMultiDragResizeConfig,
|
|
31
|
+
} from './types';
|
|
32
|
+
import { getMode } from './util';
|
|
26
33
|
|
|
27
34
|
export default class StageMultiDragResize extends MoveableOptionsManager {
|
|
28
35
|
/** 画布容器 */
|
|
@@ -34,6 +41,8 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
|
|
|
34
41
|
public dragStatus: StageDragStatus = StageDragStatus.END;
|
|
35
42
|
private dragResizeHelper: DragResizeHelper;
|
|
36
43
|
private getRenderDocument: GetRenderDocument;
|
|
44
|
+
private delayedMarkContainer: DelayedMarkContainer;
|
|
45
|
+
private markContainerEnd: MarkContainerEnd;
|
|
37
46
|
|
|
38
47
|
constructor(config: StageMultiDragResizeConfig) {
|
|
39
48
|
const moveableOptionsManagerConfig: MoveableOptionsManagerConfig = {
|
|
@@ -43,13 +52,12 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
|
|
|
43
52
|
};
|
|
44
53
|
super(moveableOptionsManagerConfig);
|
|
45
54
|
|
|
55
|
+
this.delayedMarkContainer = config.delayedMarkContainer;
|
|
56
|
+
this.markContainerEnd = config.markContainerEnd;
|
|
46
57
|
this.container = config.container;
|
|
47
58
|
this.getRenderDocument = config.getRenderDocument;
|
|
48
59
|
|
|
49
|
-
this.dragResizeHelper =
|
|
50
|
-
container: config.container,
|
|
51
|
-
updateDragEl: config.updateDragEl,
|
|
52
|
-
});
|
|
60
|
+
this.dragResizeHelper = config.dragResizeHelper;
|
|
53
61
|
|
|
54
62
|
this.on('update-moveable', () => {
|
|
55
63
|
if (this.moveableForMulti) {
|
|
@@ -85,6 +93,8 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
|
|
|
85
93
|
}),
|
|
86
94
|
);
|
|
87
95
|
|
|
96
|
+
let timeout: NodeJS.Timeout | undefined;
|
|
97
|
+
|
|
88
98
|
this.moveableForMulti
|
|
89
99
|
.on('resizeGroupStart', (e) => {
|
|
90
100
|
this.dragResizeHelper.onResizeGroupStart(e);
|
|
@@ -103,11 +113,18 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
|
|
|
103
113
|
this.dragStatus = StageDragStatus.START;
|
|
104
114
|
})
|
|
105
115
|
.on('dragGroup', (e) => {
|
|
116
|
+
if (timeout) {
|
|
117
|
+
globalThis.clearTimeout(timeout);
|
|
118
|
+
timeout = undefined;
|
|
119
|
+
}
|
|
120
|
+
timeout = this.delayedMarkContainer(e.inputEvent, this.targetList);
|
|
121
|
+
|
|
106
122
|
this.dragResizeHelper.onDragGroup(e);
|
|
107
123
|
this.dragStatus = StageDragStatus.ING;
|
|
108
124
|
})
|
|
109
125
|
.on('dragGroupEnd', () => {
|
|
110
|
-
this.
|
|
126
|
+
const parentEl = this.markContainerEnd();
|
|
127
|
+
this.update(false, parentEl);
|
|
111
128
|
this.dragStatus = StageDragStatus.END;
|
|
112
129
|
})
|
|
113
130
|
.on('clickGroup', (e) => {
|
|
@@ -182,22 +199,19 @@ export default class StageMultiDragResize extends MoveableOptionsManager {
|
|
|
182
199
|
* 拖拽完成后将更新的位置信息暴露给上层业务方,业务方可以接收事件进行保存
|
|
183
200
|
* @param isResize 是否进行大小缩放
|
|
184
201
|
*/
|
|
185
|
-
private update(isResize = false): void {
|
|
202
|
+
private update(isResize = false, parentEl: HTMLElement | null = null): void {
|
|
186
203
|
if (this.targetList.length === 0) return;
|
|
187
204
|
|
|
188
205
|
const doc = this.getRenderDocument();
|
|
189
206
|
if (!doc) return;
|
|
190
207
|
|
|
191
208
|
const data = this.targetList.map((targetItem) => {
|
|
192
|
-
const
|
|
193
|
-
const top = calcValueByFontsize(doc, targetItem.offsetTop);
|
|
194
|
-
const width = calcValueByFontsize(doc, targetItem.clientWidth);
|
|
195
|
-
const height = calcValueByFontsize(doc, targetItem.clientHeight);
|
|
209
|
+
const rect = this.dragResizeHelper.getUpdatedElRect(targetItem, parentEl, doc);
|
|
196
210
|
return {
|
|
197
211
|
el: targetItem,
|
|
198
|
-
style: isResize ?
|
|
212
|
+
style: isResize ? rect : { left: rect.left, top: rect.top },
|
|
199
213
|
};
|
|
200
214
|
});
|
|
201
|
-
this.emit('update', data,
|
|
215
|
+
this.emit('update', { data, parentEl });
|
|
202
216
|
}
|
|
203
217
|
}
|
package/src/types.ts
CHANGED
|
@@ -22,6 +22,7 @@ import Core from '@tmagic/core';
|
|
|
22
22
|
import type { Id, MApp, MContainer, MNode } from '@tmagic/schema';
|
|
23
23
|
|
|
24
24
|
import { GuidesType, ZIndex } from './const';
|
|
25
|
+
import DragResizeHelper from './DragResizeHelper';
|
|
25
26
|
import StageCore from './StageCore';
|
|
26
27
|
|
|
27
28
|
export type TargetElement = HTMLElement | SVGElement;
|
|
@@ -112,21 +113,23 @@ export interface StageMaskConfig {
|
|
|
112
113
|
|
|
113
114
|
export interface StageDragResizeConfig {
|
|
114
115
|
container: HTMLElement;
|
|
116
|
+
dragResizeHelper: DragResizeHelper;
|
|
115
117
|
moveableOptions?: CustomizeMoveableOptions;
|
|
116
118
|
disabledDragStart?: boolean;
|
|
117
119
|
getRootContainer: GetRootContainer;
|
|
118
120
|
getRenderDocument: GetRenderDocument;
|
|
119
121
|
markContainerEnd: MarkContainerEnd;
|
|
120
122
|
delayedMarkContainer: DelayedMarkContainer;
|
|
121
|
-
updateDragEl?: UpdateDragEl;
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
export interface StageMultiDragResizeConfig {
|
|
125
126
|
container: HTMLElement;
|
|
127
|
+
dragResizeHelper: DragResizeHelper;
|
|
126
128
|
multiMoveableOptions?: CustomizeMoveableOptions;
|
|
127
129
|
getRootContainer: GetRootContainer;
|
|
128
130
|
getRenderDocument: GetRenderDocument;
|
|
129
|
-
|
|
131
|
+
markContainerEnd: MarkContainerEnd;
|
|
132
|
+
delayedMarkContainer: DelayedMarkContainer;
|
|
130
133
|
}
|
|
131
134
|
|
|
132
135
|
export interface DragResizeHelperConfig {
|
|
@@ -190,6 +193,12 @@ export interface UpdateEventData {
|
|
|
190
193
|
parentEl: HTMLElement | null;
|
|
191
194
|
}
|
|
192
195
|
|
|
196
|
+
export interface RemoveEventData {
|
|
197
|
+
data: {
|
|
198
|
+
el: HTMLElement;
|
|
199
|
+
}[];
|
|
200
|
+
}
|
|
201
|
+
|
|
193
202
|
export interface SortEventData {
|
|
194
203
|
src: Id;
|
|
195
204
|
dist: Id;
|
|
@@ -244,3 +253,8 @@ export interface TargetShadowConfig {
|
|
|
244
253
|
updateDragEl?: UpdateDragEl;
|
|
245
254
|
idPrefix?: string;
|
|
246
255
|
}
|
|
256
|
+
|
|
257
|
+
export enum AbleActionEventType {
|
|
258
|
+
SELECT_PARENT = 'select-parent',
|
|
259
|
+
REMOVE = 'remove',
|
|
260
|
+
}
|
package/types/ActionManager.d.ts
CHANGED
|
@@ -100,7 +100,7 @@ export default class ActionManager extends EventEmitter {
|
|
|
100
100
|
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
101
101
|
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
102
102
|
*/
|
|
103
|
-
delayedMarkContainer(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout;
|
|
103
|
+
delayedMarkContainer(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout | undefined;
|
|
104
104
|
destroy(): void;
|
|
105
105
|
private changeCallback;
|
|
106
106
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OnDrag, OnDragGroup, OnDragGroupStart, OnDragStart, OnResize, OnResizeGroup, OnResizeGroupStart, OnResizeStart, OnRotate, OnRotateStart, OnScale, OnScaleStart } from 'moveable';
|
|
2
2
|
import MoveableHelper from 'moveable-helper';
|
|
3
3
|
import { Mode } from './const';
|
|
4
|
-
import { DragResizeHelperConfig, TargetElement } from './types';
|
|
4
|
+
import { DragResizeHelperConfig, Rect, TargetElement } from './types';
|
|
5
5
|
/**
|
|
6
6
|
* 拖拽/改变大小等操作发生时,moveable会抛出各种状态事件,DragResizeHelper负责响应这些事件,对目标节点target和拖拽节点targetShadow进行修改;
|
|
7
7
|
* 其中目标节点是DragResizeHelper直接改的,targetShadow作为直接被操作的拖拽框,是调用moveableHelper改的;
|
|
@@ -58,6 +58,7 @@ export default class DragResizeHelper {
|
|
|
58
58
|
onResizeGroup(e: OnResizeGroup): void;
|
|
59
59
|
onDragGroupStart(e: OnDragGroupStart): void;
|
|
60
60
|
onDragGroup(e: OnDragGroup): void;
|
|
61
|
+
getUpdatedElRect(el: HTMLElement, parentEl: HTMLElement | null, doc: Document): Rect;
|
|
61
62
|
/**
|
|
62
63
|
* 多选状态设置多个节点的快照
|
|
63
64
|
*/
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { MoveableManagerInterface, Renderer } from 'moveable';
|
|
2
|
-
|
|
2
|
+
import { AbleActionEventType } from './types';
|
|
3
|
+
declare const _default: (handler: (type: AbleActionEventType) => void) => {
|
|
3
4
|
name: string;
|
|
4
|
-
props: {
|
|
5
|
+
props: {
|
|
6
|
+
selectParent: BooleanConstructor;
|
|
7
|
+
};
|
|
5
8
|
events: {};
|
|
6
9
|
render(moveable: MoveableManagerInterface<any, any>, React: Renderer): any;
|
|
7
10
|
};
|
package/types/StageCore.d.ts
CHANGED
|
@@ -60,7 +60,7 @@ export default class StageCore extends EventEmitter {
|
|
|
60
60
|
/**
|
|
61
61
|
* @deprecated 废弃接口,建议用delayedMarkContainer代替
|
|
62
62
|
*/
|
|
63
|
-
getAddContainerHighlightClassNameTimeout(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout;
|
|
63
|
+
getAddContainerHighlightClassNameTimeout(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout | undefined;
|
|
64
64
|
/**
|
|
65
65
|
* 鼠标拖拽着元素,在容器上方悬停,延迟一段时间后,对容器进行标记,如果悬停时间够长将标记成功,悬停时间短,调用方通过返回的timeoutId取消标记
|
|
66
66
|
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
|
@@ -68,7 +68,7 @@ export default class StageCore extends EventEmitter {
|
|
|
68
68
|
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
69
69
|
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
70
70
|
*/
|
|
71
|
-
delayedMarkContainer(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout;
|
|
71
|
+
delayedMarkContainer(event: MouseEvent, excludeElList?: Element[]): NodeJS.Timeout | undefined;
|
|
72
72
|
/**
|
|
73
73
|
* 销毁实例
|
|
74
74
|
*/
|