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