@tmagic/stage 1.0.0-rc.1 → 1.0.0-rc.12
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.es.js +229 -131
- package/dist/tmagic-stage.es.js.map +1 -1
- package/dist/tmagic-stage.umd.js +229 -131
- package/dist/tmagic-stage.umd.js.map +1 -1
- package/dist/types/src/StageCore.d.ts +1 -1
- package/dist/types/src/StageDragResize.d.ts +14 -2
- package/dist/types/src/StageMask.d.ts +2 -0
- package/dist/types/src/TargetCalibrate.d.ts +3 -1
- package/dist/types/src/const.d.ts +24 -1
- package/dist/types/src/types.d.ts +13 -4
- package/dist/types/src/util.d.ts +3 -2
- package/package.json +5 -5
- package/src/Rule.ts +13 -5
- package/src/StageCore.ts +8 -3
- package/src/StageDragResize.ts +153 -64
- package/src/StageHighlight.ts +1 -0
- package/src/StageMask.ts +37 -6
- package/src/StageRender.ts +11 -16
- package/src/TargetCalibrate.ts +15 -31
- package/src/const.ts +24 -2
- package/src/types.ts +14 -4
- package/src/util.ts +46 -33
- package/LICENSE +0 -5432
|
@@ -1,23 +1,46 @@
|
|
|
1
|
+
/** 流式布局下拖动时需要clone一个镜像节点,镜像节点的id前缀 */
|
|
1
2
|
export declare const GHOST_EL_ID_PREFIX = "ghost_el_";
|
|
3
|
+
/** 拖动的时候需要在蒙层中创建一个占位节点,该节点的id前缀 */
|
|
2
4
|
export declare const DRAG_EL_ID_PREFIX = "drag_el_";
|
|
5
|
+
/** 高亮时需要在蒙层中创建一个占位节点,该节点的id前缀 */
|
|
3
6
|
export declare const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
|
|
7
|
+
/** 默认放到缩小倍数 */
|
|
4
8
|
export declare const DEFAULT_ZOOM = 1;
|
|
9
|
+
/** 参考线类型 */
|
|
5
10
|
export declare enum GuidesType {
|
|
11
|
+
/** 水平 */
|
|
6
12
|
HORIZONTAL = "horizontal",
|
|
13
|
+
/** 垂直 */
|
|
7
14
|
VERTICAL = "vertical"
|
|
8
15
|
}
|
|
16
|
+
/** css z-index */
|
|
9
17
|
export declare enum ZIndex {
|
|
18
|
+
/** 蒙层,用于监听用户操作,需要置于顶层 */
|
|
10
19
|
MASK = "99999",
|
|
11
|
-
|
|
20
|
+
/** 选中的节点 */
|
|
21
|
+
SELECTED_EL = "666",
|
|
22
|
+
GHOST_EL = "700",
|
|
23
|
+
DRAG_EL = "9"
|
|
12
24
|
}
|
|
25
|
+
/** 鼠标按键 */
|
|
13
26
|
export declare enum MouseButton {
|
|
27
|
+
/** 左键 */
|
|
14
28
|
LEFT = 0,
|
|
29
|
+
/** z中健 */
|
|
15
30
|
MIDDLE = 1,
|
|
31
|
+
/** 右键 */
|
|
16
32
|
RIGHT = 2
|
|
17
33
|
}
|
|
34
|
+
/** 布局方式 */
|
|
18
35
|
export declare enum Mode {
|
|
36
|
+
/** 绝对定位布局 */
|
|
19
37
|
ABSOLUTE = "absolute",
|
|
38
|
+
/** 固定定位布局 */
|
|
20
39
|
FIXED = "fixed",
|
|
40
|
+
/** 流式布局 */
|
|
21
41
|
SORTABLE = "sortable"
|
|
22
42
|
}
|
|
43
|
+
/** 选中节点的class name */
|
|
23
44
|
export declare const SELECTED_CLASS = "tmagic-stage-selected-area";
|
|
45
|
+
export declare const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
|
|
46
|
+
export declare const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { MoveableOptions } from '
|
|
1
|
+
import { MoveableOptions } from 'moveable';
|
|
2
|
+
import Core from '@tmagic/core';
|
|
2
3
|
import { Id, MApp, MNode } from '@tmagic/schema';
|
|
3
4
|
import { GuidesType } from './const';
|
|
4
5
|
import StageCore from './StageCore';
|
|
@@ -15,6 +16,8 @@ export declare type StageCoreConfig = {
|
|
|
15
16
|
/** runtime 的HTML地址,可以是一个HTTP地址,如果和编辑器不同域,需要设置跨域,也可以是一个相对或绝对路径 */
|
|
16
17
|
runtimeUrl?: string;
|
|
17
18
|
render?: (renderer: StageCore) => Promise<HTMLElement> | HTMLElement;
|
|
19
|
+
autoScrollIntoView?: boolean;
|
|
20
|
+
updateDragEl?: (el: HTMLDivElement, target: HTMLElement) => void;
|
|
18
21
|
};
|
|
19
22
|
export interface StageRenderConfig {
|
|
20
23
|
core: StageCore;
|
|
@@ -42,10 +45,14 @@ export interface UpdateEventData {
|
|
|
42
45
|
el: HTMLElement;
|
|
43
46
|
ghostEl: HTMLElement;
|
|
44
47
|
style: {
|
|
45
|
-
width
|
|
46
|
-
height
|
|
48
|
+
width?: number;
|
|
49
|
+
height?: number;
|
|
47
50
|
left?: number;
|
|
48
51
|
top?: number;
|
|
52
|
+
transform?: {
|
|
53
|
+
rotate?: string;
|
|
54
|
+
scale?: string;
|
|
55
|
+
};
|
|
49
56
|
};
|
|
50
57
|
}
|
|
51
58
|
export interface SortEventData {
|
|
@@ -62,9 +69,10 @@ export interface RemoveData {
|
|
|
62
69
|
root: MApp;
|
|
63
70
|
}
|
|
64
71
|
export interface Runtime {
|
|
72
|
+
getApp?: () => Core;
|
|
65
73
|
beforeSelect?: (el: HTMLElement) => Promise<boolean> | boolean;
|
|
66
74
|
getSnapElements?: (el?: HTMLElement) => HTMLElement[];
|
|
67
|
-
updateRootConfig
|
|
75
|
+
updateRootConfig?: (config: MApp) => void;
|
|
68
76
|
updatePageId?: (id: Id) => void;
|
|
69
77
|
select?: (id: Id) => Promise<HTMLElement> | HTMLElement;
|
|
70
78
|
add?: (data: UpdateData) => void;
|
|
@@ -88,4 +96,5 @@ export interface TargetCalibrateConfig {
|
|
|
88
96
|
parent: HTMLElement;
|
|
89
97
|
mask: StageMask;
|
|
90
98
|
dr: StageDragResize;
|
|
99
|
+
core: StageCore;
|
|
91
100
|
}
|
package/dist/types/src/util.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Mode } from './const';
|
|
1
|
+
import { GuidesType, Mode } from './const';
|
|
2
2
|
import type { Offset } from './types';
|
|
3
3
|
export declare const getOffset: (el: HTMLElement) => Offset;
|
|
4
4
|
export declare const getAbsolutePosition: (el: HTMLElement, { top, left }: Offset) => {
|
|
@@ -19,4 +19,5 @@ export declare const createDiv: ({ className, cssText }: {
|
|
|
19
19
|
cssText: string;
|
|
20
20
|
}) => HTMLDivElement;
|
|
21
21
|
export declare const removeSelectedClassName: (doc: Document) => void;
|
|
22
|
-
export declare const addSelectedClassName: (el: Element) => void;
|
|
22
|
+
export declare const addSelectedClassName: (el: Element, doc: Document) => void;
|
|
23
|
+
export declare const getGuideLineFromCache: (type: GuidesType) => number[];
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.0.0-rc.
|
|
2
|
+
"version": "1.0.0-rc.12",
|
|
3
3
|
"name": "@tmagic/stage",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"dist/*"
|
|
@@ -27,8 +27,9 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@scena/guides": "^0.17.0",
|
|
30
|
-
"@tmagic/
|
|
31
|
-
"@tmagic/
|
|
30
|
+
"@tmagic/core": "1.0.0-rc.12",
|
|
31
|
+
"@tmagic/schema": "1.0.0-rc.12",
|
|
32
|
+
"@tmagic/utils": "1.0.0-rc.12",
|
|
32
33
|
"events": "^3.3.0",
|
|
33
34
|
"lodash-es": "^4.17.21",
|
|
34
35
|
"moveable": "^0.29.4",
|
|
@@ -42,6 +43,5 @@
|
|
|
42
43
|
"typescript": "^4.3.4",
|
|
43
44
|
"vite": "^2.3.7",
|
|
44
45
|
"vite-plugin-dts": "^0.9.6"
|
|
45
|
-
}
|
|
46
|
-
"gitHead": "3b647794d087888bfec9772f54356fa48c0b6d90"
|
|
46
|
+
}
|
|
47
47
|
}
|
package/src/Rule.ts
CHANGED
|
@@ -2,13 +2,14 @@ import EventEmitter from 'events';
|
|
|
2
2
|
|
|
3
3
|
import Guides, { GuidesEvents } from '@scena/guides';
|
|
4
4
|
|
|
5
|
-
import { GuidesType } from './const';
|
|
5
|
+
import { GuidesType, H_GUIDE_LINE_STORAGE_KEY, V_GUIDE_LINE_STORAGE_KEY } from './const';
|
|
6
|
+
import { getGuideLineFromCache } from './util';
|
|
6
7
|
|
|
7
8
|
export default class Rule extends EventEmitter {
|
|
8
9
|
public hGuides: Guides;
|
|
9
10
|
public vGuides: Guides;
|
|
10
|
-
public horizontalGuidelines: number[] =
|
|
11
|
-
public verticalGuidelines: number[] =
|
|
11
|
+
public horizontalGuidelines: number[] = getGuideLineFromCache(GuidesType.HORIZONTAL);
|
|
12
|
+
public verticalGuidelines: number[] = getGuideLineFromCache(GuidesType.VERTICAL);
|
|
12
13
|
|
|
13
14
|
private container: HTMLDivElement;
|
|
14
15
|
private containerResizeObserver: ResizeObserver;
|
|
@@ -17,8 +18,8 @@ export default class Rule extends EventEmitter {
|
|
|
17
18
|
super();
|
|
18
19
|
|
|
19
20
|
this.container = container;
|
|
20
|
-
this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
|
|
21
|
-
this.vGuides = this.createGuides(GuidesType.VERTICAL);
|
|
21
|
+
this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
|
|
22
|
+
this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
|
|
22
23
|
|
|
23
24
|
this.hGuides.on('changeGuides', this.hGuidesChangeGuidesHandler);
|
|
24
25
|
this.vGuides.on('changeGuides', this.vGuidesChangeGuidesHandler);
|
|
@@ -68,6 +69,9 @@ export default class Rule extends EventEmitter {
|
|
|
68
69
|
type: GuidesType.HORIZONTAL,
|
|
69
70
|
guides: [],
|
|
70
71
|
});
|
|
72
|
+
|
|
73
|
+
globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, '[]');
|
|
74
|
+
globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, '[]');
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
/**
|
|
@@ -138,6 +142,8 @@ export default class Rule extends EventEmitter {
|
|
|
138
142
|
type: GuidesType.HORIZONTAL,
|
|
139
143
|
guides: this.horizontalGuidelines,
|
|
140
144
|
});
|
|
145
|
+
|
|
146
|
+
globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
|
|
141
147
|
};
|
|
142
148
|
|
|
143
149
|
private vGuidesChangeGuidesHandler = (e: GuidesEvents['changeGuides']) => {
|
|
@@ -146,5 +152,7 @@ export default class Rule extends EventEmitter {
|
|
|
146
152
|
type: GuidesType.VERTICAL,
|
|
147
153
|
guides: this.verticalGuidelines,
|
|
148
154
|
});
|
|
155
|
+
|
|
156
|
+
globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
|
|
149
157
|
};
|
|
150
158
|
}
|
package/src/StageCore.ts
CHANGED
|
@@ -155,12 +155,17 @@ export default class StageCore extends EventEmitter {
|
|
|
155
155
|
|
|
156
156
|
this.mask.setLayout(el);
|
|
157
157
|
this.dr.select(el, event);
|
|
158
|
+
|
|
159
|
+
if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
|
|
160
|
+
this.mask.intersectionObserver?.observe(el);
|
|
161
|
+
}
|
|
162
|
+
|
|
158
163
|
this.selectedDom = el;
|
|
159
164
|
|
|
160
165
|
if (this.renderer.contentWindow) {
|
|
161
166
|
removeSelectedClassName(this.renderer.contentWindow.document);
|
|
162
167
|
if (this.selectedDom) {
|
|
163
|
-
addSelectedClassName(this.selectedDom);
|
|
168
|
+
addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
|
|
164
169
|
}
|
|
165
170
|
}
|
|
166
171
|
}
|
|
@@ -225,11 +230,11 @@ export default class StageCore extends EventEmitter {
|
|
|
225
230
|
* 挂载Dom节点
|
|
226
231
|
* @param el 将stage挂载到该Dom节点上
|
|
227
232
|
*/
|
|
228
|
-
public mount(el: HTMLDivElement)
|
|
233
|
+
public async mount(el: HTMLDivElement) {
|
|
229
234
|
this.container = el;
|
|
230
235
|
const { mask, renderer } = this;
|
|
231
236
|
|
|
232
|
-
renderer.mount(el);
|
|
237
|
+
await renderer.mount(el);
|
|
233
238
|
mask.mount(el);
|
|
234
239
|
|
|
235
240
|
this.emit('mounted');
|
package/src/StageDragResize.ts
CHANGED
|
@@ -23,14 +23,18 @@ import type { MoveableOptions } from 'moveable';
|
|
|
23
23
|
import Moveable from 'moveable';
|
|
24
24
|
import MoveableHelper from 'moveable-helper';
|
|
25
25
|
|
|
26
|
-
import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode } from './const';
|
|
26
|
+
import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, GuidesType, Mode, ZIndex } from './const';
|
|
27
27
|
import StageCore from './StageCore';
|
|
28
|
-
import type {
|
|
29
|
-
import { getAbsolutePosition, getMode, getOffset } from './util';
|
|
28
|
+
import type { SortEventData, StageDragResizeConfig } from './types';
|
|
29
|
+
import { getAbsolutePosition, getGuideLineFromCache, getMode, getOffset } from './util';
|
|
30
30
|
|
|
31
|
+
/** 拖动状态 */
|
|
31
32
|
enum ActionStatus {
|
|
33
|
+
/** 开始拖动 */
|
|
32
34
|
START = 'start',
|
|
35
|
+
/** 拖动中 */
|
|
33
36
|
ING = 'ing',
|
|
37
|
+
/** 拖动结束 */
|
|
34
38
|
END = 'end',
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -39,17 +43,27 @@ enum ActionStatus {
|
|
|
39
43
|
*/
|
|
40
44
|
export default class StageDragResize extends EventEmitter {
|
|
41
45
|
public core: StageCore;
|
|
46
|
+
/** 画布容器 */
|
|
42
47
|
public container: HTMLElement;
|
|
48
|
+
/** 目标节点 */
|
|
43
49
|
public target?: HTMLElement;
|
|
44
|
-
|
|
50
|
+
/** 目标节点在蒙层中的占位节点 */
|
|
51
|
+
public dragEl: HTMLDivElement;
|
|
52
|
+
/** Moveable拖拽类实例 */
|
|
45
53
|
public moveable?: Moveable;
|
|
46
|
-
|
|
47
|
-
public
|
|
54
|
+
/** 水平参考线 */
|
|
55
|
+
public horizontalGuidelines: number[] = getGuideLineFromCache(GuidesType.HORIZONTAL);
|
|
56
|
+
/** 垂直参考线 */
|
|
57
|
+
public verticalGuidelines: number[] = getGuideLineFromCache(GuidesType.VERTICAL);
|
|
58
|
+
/** 对齐元素集合 */
|
|
48
59
|
public elementGuidelines: HTMLElement[] = [];
|
|
60
|
+
/** 布局方式:流式布局、绝对定位、固定定位 */
|
|
49
61
|
public mode: Mode = Mode.ABSOLUTE;
|
|
50
62
|
|
|
51
63
|
private moveableOptions: MoveableOptions = {};
|
|
64
|
+
/** 拖动状态 */
|
|
52
65
|
private dragStatus: ActionStatus = ActionStatus.END;
|
|
66
|
+
/** 流式布局下,目标节点的镜像节点 */
|
|
53
67
|
private ghostEl: HTMLElement | undefined;
|
|
54
68
|
private moveableHelper?: MoveableHelper;
|
|
55
69
|
|
|
@@ -73,10 +87,9 @@ export default class StageDragResize extends EventEmitter {
|
|
|
73
87
|
const oldTarget = this.target;
|
|
74
88
|
this.target = el;
|
|
75
89
|
|
|
76
|
-
this.init(el);
|
|
77
|
-
|
|
78
90
|
// 从不能拖动到能拖动的节点之间切换,要重新创建moveable,不然dragStart不生效
|
|
79
91
|
if (!this.moveable || this.target !== oldTarget) {
|
|
92
|
+
this.init(el);
|
|
80
93
|
this.moveableHelper = MoveableHelper.create({
|
|
81
94
|
useBeforeRender: true,
|
|
82
95
|
useRender: false,
|
|
@@ -98,7 +111,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
98
111
|
*/
|
|
99
112
|
public updateMoveable(el = this.target): void {
|
|
100
113
|
if (!this.moveable) throw new Error('未初始化moveable');
|
|
101
|
-
if (!el) throw new Error('
|
|
114
|
+
if (!el) throw new Error('未选中任何节点');
|
|
102
115
|
|
|
103
116
|
this.target = el;
|
|
104
117
|
|
|
@@ -157,6 +170,29 @@ export default class StageDragResize extends EventEmitter {
|
|
|
157
170
|
});
|
|
158
171
|
}
|
|
159
172
|
|
|
173
|
+
private setElementGuidelines(nodes: HTMLElement[]) {
|
|
174
|
+
this.elementGuidelines.forEach((node) => {
|
|
175
|
+
node.remove();
|
|
176
|
+
});
|
|
177
|
+
this.elementGuidelines = [];
|
|
178
|
+
|
|
179
|
+
if (this.mode === Mode.ABSOLUTE) {
|
|
180
|
+
const frame = document.createDocumentFragment();
|
|
181
|
+
|
|
182
|
+
for (const node of nodes) {
|
|
183
|
+
const { width, height } = node.getBoundingClientRect();
|
|
184
|
+
if (node === this.target) continue;
|
|
185
|
+
const { left, top } = getOffset(node as HTMLElement);
|
|
186
|
+
const elementGuideline = document.createElement('div');
|
|
187
|
+
elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
|
|
188
|
+
this.elementGuidelines.push(elementGuideline);
|
|
189
|
+
frame.append(elementGuideline);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.container.append(frame);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
160
196
|
private initMoveable() {
|
|
161
197
|
this.moveable?.destroy();
|
|
162
198
|
|
|
@@ -166,49 +202,47 @@ export default class StageDragResize extends EventEmitter {
|
|
|
166
202
|
|
|
167
203
|
this.bindResizeEvent();
|
|
168
204
|
this.bindDragEvent();
|
|
205
|
+
this.bindRotateEvent();
|
|
206
|
+
this.bindScaleEvent();
|
|
169
207
|
}
|
|
170
208
|
|
|
171
209
|
private bindResizeEvent(): void {
|
|
172
|
-
if (!this.moveable) throw new Error('moveable
|
|
210
|
+
if (!this.moveable) throw new Error('moveable 未初始化');
|
|
173
211
|
|
|
174
212
|
const frame = {
|
|
175
|
-
|
|
213
|
+
left: 0,
|
|
214
|
+
top: 0,
|
|
176
215
|
};
|
|
177
216
|
|
|
178
217
|
this.moveable
|
|
179
218
|
.on('resizeStart', (e) => {
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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;
|
|
185
226
|
})
|
|
186
|
-
.on('resize', (
|
|
227
|
+
.on('resize', (e) => {
|
|
228
|
+
const { width, height, drag } = e;
|
|
187
229
|
if (!this.moveable || !this.target || !this.dragEl) return;
|
|
188
230
|
|
|
189
231
|
const { beforeTranslate } = drag;
|
|
190
|
-
frame.translate = beforeTranslate;
|
|
191
232
|
this.dragStatus = ActionStatus.ING;
|
|
192
233
|
|
|
193
|
-
this.
|
|
194
|
-
this.target.style.height = `${height}px`;
|
|
195
|
-
this.dragEl.style.width = `${width}px`;
|
|
196
|
-
this.dragEl.style.height = `${height}px`;
|
|
234
|
+
this.moveableHelper?.onResize(e);
|
|
197
235
|
|
|
198
236
|
// 流式布局
|
|
199
237
|
if (this.mode === Mode.SORTABLE) {
|
|
200
|
-
this.
|
|
201
|
-
|
|
202
|
-
|
|
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`;
|
|
203
242
|
}
|
|
204
243
|
|
|
205
|
-
this.
|
|
206
|
-
this.
|
|
207
|
-
|
|
208
|
-
const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
|
|
209
|
-
|
|
210
|
-
this.target.style.left = `${offset.left}px`;
|
|
211
|
-
this.target.style.top = `${offset.top}px`;
|
|
244
|
+
this.target.style.width = `${width}px`;
|
|
245
|
+
this.target.style.height = `${height}px`;
|
|
212
246
|
})
|
|
213
247
|
.on('resizeEnd', () => {
|
|
214
248
|
this.dragStatus = ActionStatus.END;
|
|
@@ -217,9 +251,12 @@ export default class StageDragResize extends EventEmitter {
|
|
|
217
251
|
}
|
|
218
252
|
|
|
219
253
|
private bindDragEvent(): void {
|
|
220
|
-
if (!this.moveable) throw new Error('moveable
|
|
254
|
+
if (!this.moveable) throw new Error('moveable 未初始化');
|
|
221
255
|
|
|
222
|
-
|
|
256
|
+
const frame = {
|
|
257
|
+
left: 0,
|
|
258
|
+
top: 0,
|
|
259
|
+
};
|
|
223
260
|
|
|
224
261
|
this.moveable
|
|
225
262
|
.on('dragStart', (e) => {
|
|
@@ -232,29 +269,25 @@ export default class StageDragResize extends EventEmitter {
|
|
|
232
269
|
if (this.mode === Mode.SORTABLE) {
|
|
233
270
|
this.ghostEl = this.generateGhostEl(this.target);
|
|
234
271
|
}
|
|
272
|
+
|
|
273
|
+
frame.top = this.target.offsetTop;
|
|
274
|
+
frame.left = this.target.offsetLeft;
|
|
235
275
|
})
|
|
236
276
|
.on('drag', (e) => {
|
|
237
277
|
if (!this.target || !this.dragEl) return;
|
|
238
278
|
|
|
239
|
-
if (!offset) {
|
|
240
|
-
offset = getAbsolutePosition(this.target, { left: 0, top: 0 });
|
|
241
|
-
}
|
|
242
|
-
|
|
243
279
|
this.dragStatus = ActionStatus.ING;
|
|
244
280
|
|
|
245
|
-
const { left, top } = e;
|
|
246
|
-
|
|
247
281
|
// 流式布局
|
|
248
282
|
if (this.ghostEl) {
|
|
249
|
-
this.
|
|
250
|
-
this.ghostEl.style.top = `${top + offset.top}px`;
|
|
283
|
+
this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
251
284
|
return;
|
|
252
285
|
}
|
|
253
286
|
|
|
254
287
|
this.moveableHelper?.onDrag(e);
|
|
255
288
|
|
|
256
|
-
this.target.style.left = `${left +
|
|
257
|
-
this.target.style.top = `${top +
|
|
289
|
+
this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
|
|
290
|
+
this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
258
291
|
})
|
|
259
292
|
.on('dragEnd', () => {
|
|
260
293
|
// 点击不拖动时会触发dragStart和dragEnd,但是不会有drag事件
|
|
@@ -267,24 +300,64 @@ export default class StageDragResize extends EventEmitter {
|
|
|
267
300
|
this.update();
|
|
268
301
|
}
|
|
269
302
|
}
|
|
270
|
-
offset = null;
|
|
271
303
|
|
|
272
304
|
this.dragStatus = ActionStatus.END;
|
|
273
305
|
this.destroyGhostEl();
|
|
274
306
|
});
|
|
275
307
|
}
|
|
276
308
|
|
|
277
|
-
private
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
(() => {
|
|
282
|
-
|
|
283
|
-
|
|
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
|
+
});
|
|
284
360
|
});
|
|
285
|
-
return getSnapElements(el).filter(
|
|
286
|
-
(element) => element !== this.target && !this.target?.contains(element) && element !== mask.page,
|
|
287
|
-
);
|
|
288
361
|
}
|
|
289
362
|
|
|
290
363
|
private sort(): void {
|
|
@@ -307,14 +380,15 @@ export default class StageDragResize extends EventEmitter {
|
|
|
307
380
|
}
|
|
308
381
|
|
|
309
382
|
private update(isResize = false): void {
|
|
310
|
-
|
|
383
|
+
if (!this.target) return;
|
|
384
|
+
|
|
311
385
|
const offset =
|
|
312
|
-
this.mode === Mode.SORTABLE ? { left: 0, top: 0 } :
|
|
386
|
+
this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
|
|
313
387
|
|
|
314
388
|
const left = this.calcValueByFontsize(offset.left);
|
|
315
389
|
const top = this.calcValueByFontsize(offset.top);
|
|
316
|
-
const width = this.calcValueByFontsize(
|
|
317
|
-
const height = this.calcValueByFontsize(
|
|
390
|
+
const width = this.calcValueByFontsize(this.target.clientWidth);
|
|
391
|
+
const height = this.calcValueByFontsize(this.target.clientHeight);
|
|
318
392
|
|
|
319
393
|
this.emit('update', {
|
|
320
394
|
el: this.target,
|
|
@@ -330,7 +404,7 @@ export default class StageDragResize extends EventEmitter {
|
|
|
330
404
|
const ghostEl = el.cloneNode(true) as HTMLElement;
|
|
331
405
|
const { top, left } = getAbsolutePosition(el, getOffset(el));
|
|
332
406
|
ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
|
|
333
|
-
ghostEl.style.zIndex =
|
|
407
|
+
ghostEl.style.zIndex = ZIndex.GHOST_EL;
|
|
334
408
|
ghostEl.style.opacity = '.5';
|
|
335
409
|
ghostEl.style.position = 'absolute';
|
|
336
410
|
ghostEl.style.left = `${left}px`;
|
|
@@ -345,19 +419,24 @@ export default class StageDragResize extends EventEmitter {
|
|
|
345
419
|
}
|
|
346
420
|
|
|
347
421
|
private updateDragEl(el: HTMLElement) {
|
|
348
|
-
const { width, height } = el.getBoundingClientRect();
|
|
349
422
|
const offset = getOffset(el);
|
|
423
|
+
const { transform } = getComputedStyle(el);
|
|
350
424
|
|
|
351
425
|
this.dragEl.style.cssText = `
|
|
352
426
|
position: absolute;
|
|
427
|
+
transform: ${transform};
|
|
353
428
|
left: ${offset.left}px;
|
|
354
429
|
top: ${offset.top}px;
|
|
355
|
-
width: ${
|
|
356
|
-
height: ${
|
|
357
|
-
z-index:
|
|
430
|
+
width: ${el.clientWidth}px;
|
|
431
|
+
height: ${el.clientHeight}px;
|
|
432
|
+
z-index: ${ZIndex.DRAG_EL};
|
|
358
433
|
`;
|
|
359
434
|
|
|
360
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
|
+
}
|
|
361
440
|
}
|
|
362
441
|
|
|
363
442
|
private destroyDragEl(): void {
|
|
@@ -376,6 +455,14 @@ export default class StageDragResize extends EventEmitter {
|
|
|
376
455
|
moveableOptions = moveableOptions(this.core);
|
|
377
456
|
}
|
|
378
457
|
|
|
458
|
+
const elementGuidelines: any = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
|
|
459
|
+
|
|
460
|
+
this.setElementGuidelines(elementGuidelines);
|
|
461
|
+
|
|
462
|
+
if (moveableOptions.elementGuidelines) {
|
|
463
|
+
delete moveableOptions.elementGuidelines;
|
|
464
|
+
}
|
|
465
|
+
|
|
379
466
|
return {
|
|
380
467
|
origin: false,
|
|
381
468
|
rootContainer: this.core.container,
|
|
@@ -383,6 +470,8 @@ export default class StageDragResize extends EventEmitter {
|
|
|
383
470
|
dragArea: false,
|
|
384
471
|
draggable: true,
|
|
385
472
|
resizable: true,
|
|
473
|
+
scalable: false,
|
|
474
|
+
rotatable: false,
|
|
386
475
|
snappable: isAbsolute || isFixed,
|
|
387
476
|
snapGap: isAbsolute || isFixed,
|
|
388
477
|
snapThreshold: 5,
|