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