@tmagic/stage 1.0.0-beta.8 → 1.0.0-rc.10
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 +1 -0
- package/dist/tmagic-stage.es.js +609 -273
- package/dist/tmagic-stage.es.js.map +1 -1
- package/dist/tmagic-stage.umd.js +613 -279
- package/dist/tmagic-stage.umd.js.map +1 -1
- package/dist/types/src/StageCore.d.ts +14 -4
- package/dist/types/src/StageDragResize.d.ts +22 -7
- package/dist/types/src/StageHighlight.d.ts +27 -0
- package/dist/types/src/StageMask.d.ts +23 -0
- package/dist/types/src/TargetCalibrate.d.ts +20 -0
- package/dist/types/src/const.d.ts +28 -1
- package/dist/types/src/types.d.ts +25 -5
- package/dist/types/src/util.d.ts +4 -1
- package/package.json +13 -8
- package/src/Rule.ts +13 -5
- package/src/StageCore.ts +90 -24
- package/src/StageDragResize.ts +239 -99
- package/src/StageHighlight.ts +82 -0
- package/src/StageMask.ts +106 -26
- package/src/StageRender.ts +1 -0
- package/src/TargetCalibrate.ts +119 -0
- package/src/const.ts +31 -2
- package/src/types.ts +27 -5
- package/src/util.ts +53 -28
- package/LICENSE +0 -5432
- package/tsconfig.json +0 -9
- package/vite.config.ts +0 -27
package/dist/tmagic-stage.es.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import EventEmitter$1, { EventEmitter } from 'events';
|
|
2
2
|
import Moveable from 'moveable';
|
|
3
|
+
import MoveableHelper from 'moveable-helper';
|
|
4
|
+
import { throttle } from 'lodash-es';
|
|
3
5
|
import Guides from '@scena/guides';
|
|
4
6
|
|
|
5
7
|
const GHOST_EL_ID_PREFIX = "ghost_el_";
|
|
8
|
+
const DRAG_EL_ID_PREFIX = "drag_el_";
|
|
9
|
+
const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
|
|
6
10
|
const DEFAULT_ZOOM = 1;
|
|
7
11
|
var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
|
|
8
12
|
GuidesType2["HORIZONTAL"] = "horizontal";
|
|
@@ -11,6 +15,9 @@ var GuidesType = /* @__PURE__ */ ((GuidesType2) => {
|
|
|
11
15
|
})(GuidesType || {});
|
|
12
16
|
var ZIndex = /* @__PURE__ */ ((ZIndex2) => {
|
|
13
17
|
ZIndex2["MASK"] = "99999";
|
|
18
|
+
ZIndex2["SELECTED_EL"] = "666";
|
|
19
|
+
ZIndex2["GHOST_EL"] = "700";
|
|
20
|
+
ZIndex2["DRAG_EL"] = "9";
|
|
14
21
|
return ZIndex2;
|
|
15
22
|
})(ZIndex || {});
|
|
16
23
|
var MouseButton = /* @__PURE__ */ ((MouseButton2) => {
|
|
@@ -25,31 +32,23 @@ var Mode = /* @__PURE__ */ ((Mode2) => {
|
|
|
25
32
|
Mode2["SORTABLE"] = "sortable";
|
|
26
33
|
return Mode2;
|
|
27
34
|
})(Mode || {});
|
|
35
|
+
const SELECTED_CLASS = "tmagic-stage-selected-area";
|
|
36
|
+
const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
|
|
37
|
+
const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
|
|
28
38
|
|
|
39
|
+
const getParents = (el, relative) => {
|
|
40
|
+
let cur = el.parentElement;
|
|
41
|
+
const parents = [];
|
|
42
|
+
while (cur && cur !== relative) {
|
|
43
|
+
parents.push(cur);
|
|
44
|
+
cur = cur.parentElement;
|
|
45
|
+
}
|
|
46
|
+
return parents;
|
|
47
|
+
};
|
|
29
48
|
const getOffset = (el) => {
|
|
30
|
-
const { transform } = getComputedStyle(el);
|
|
31
49
|
const { offsetParent } = el;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (transform.indexOf("matrix") > -1) {
|
|
35
|
-
let a = 1;
|
|
36
|
-
let b = 1;
|
|
37
|
-
let c = 1;
|
|
38
|
-
let d = 1;
|
|
39
|
-
let e = 0;
|
|
40
|
-
let f = 0;
|
|
41
|
-
transform.replace(/matrix\((.+), (.+), (.+), (.+), (.+), (.+)\)/, ($0, $1, $2, $3, $4, $5, $6) => {
|
|
42
|
-
a = +$1;
|
|
43
|
-
b = +$2;
|
|
44
|
-
c = +$3;
|
|
45
|
-
d = +$4;
|
|
46
|
-
e = +$5;
|
|
47
|
-
f = +$6;
|
|
48
|
-
return transform;
|
|
49
|
-
});
|
|
50
|
-
left = a * left + c * top + e;
|
|
51
|
-
top = b * left + d * top + f;
|
|
52
|
-
}
|
|
50
|
+
const left = el.offsetLeft;
|
|
51
|
+
const top = el.offsetTop;
|
|
53
52
|
if (offsetParent) {
|
|
54
53
|
const parentOffset = getOffset(offsetParent);
|
|
55
54
|
return {
|
|
@@ -145,46 +144,81 @@ const createDiv = ({ className, cssText }) => {
|
|
|
145
144
|
el.style.cssText = cssText;
|
|
146
145
|
return el;
|
|
147
146
|
};
|
|
147
|
+
const removeSelectedClassName = (doc) => {
|
|
148
|
+
const oldEl = doc.querySelector(`.${SELECTED_CLASS}`);
|
|
149
|
+
if (oldEl) {
|
|
150
|
+
oldEl.classList.remove(SELECTED_CLASS);
|
|
151
|
+
oldEl.parentNode?.classList.remove(`${SELECTED_CLASS}-parent`);
|
|
152
|
+
doc.querySelectorAll(`.${SELECTED_CLASS}-parents`).forEach((item) => {
|
|
153
|
+
item.classList.remove(`${SELECTED_CLASS}-parents`);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const addSelectedClassName = (el, doc) => {
|
|
158
|
+
el.classList.add(SELECTED_CLASS);
|
|
159
|
+
el.parentNode?.classList.add(`${SELECTED_CLASS}-parent`);
|
|
160
|
+
getParents(el, doc.body).forEach((item) => {
|
|
161
|
+
item.classList.add(`${SELECTED_CLASS}-parents`);
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
const getGuideLineFromCache = (type) => {
|
|
165
|
+
const key = {
|
|
166
|
+
[GuidesType.HORIZONTAL]: H_GUIDE_LINE_STORAGE_KEY,
|
|
167
|
+
[GuidesType.VERTICAL]: V_GUIDE_LINE_STORAGE_KEY
|
|
168
|
+
}[type];
|
|
169
|
+
if (!key)
|
|
170
|
+
return [];
|
|
171
|
+
const guideLineCacheData = globalThis.localStorage.getItem(key);
|
|
172
|
+
if (guideLineCacheData) {
|
|
173
|
+
try {
|
|
174
|
+
return JSON.parse(guideLineCacheData) || [];
|
|
175
|
+
} catch (e) {
|
|
176
|
+
console.error(e);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return [];
|
|
180
|
+
};
|
|
148
181
|
|
|
149
182
|
class StageDragResize extends EventEmitter {
|
|
150
|
-
core;
|
|
151
|
-
container;
|
|
152
|
-
target;
|
|
153
|
-
dragEl;
|
|
154
|
-
moveable;
|
|
155
|
-
horizontalGuidelines = [];
|
|
156
|
-
verticalGuidelines = [];
|
|
157
|
-
moveableOptions = {};
|
|
158
|
-
dragStatus = "end" /* END */;
|
|
159
|
-
ghostEl;
|
|
160
|
-
mode = Mode.ABSOLUTE;
|
|
161
183
|
constructor(config) {
|
|
162
184
|
super();
|
|
185
|
+
this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
|
|
186
|
+
this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
|
|
187
|
+
this.elementGuidelines = [];
|
|
188
|
+
this.mode = Mode.ABSOLUTE;
|
|
189
|
+
this.moveableOptions = {};
|
|
190
|
+
this.dragStatus = "end" /* END */;
|
|
163
191
|
this.core = config.core;
|
|
164
192
|
this.container = config.container;
|
|
193
|
+
this.dragEl = globalThis.document.createElement("div");
|
|
194
|
+
this.container.append(this.dragEl);
|
|
165
195
|
}
|
|
166
|
-
|
|
196
|
+
select(el, event) {
|
|
197
|
+
const oldTarget = this.target;
|
|
167
198
|
this.target = el;
|
|
168
|
-
if (
|
|
169
|
-
this.
|
|
199
|
+
if (!this.moveable || this.target !== oldTarget) {
|
|
200
|
+
this.init(el);
|
|
201
|
+
this.moveableHelper = MoveableHelper.create({
|
|
202
|
+
useBeforeRender: true,
|
|
203
|
+
useRender: false,
|
|
204
|
+
createAuto: true
|
|
205
|
+
});
|
|
206
|
+
this.initMoveable();
|
|
207
|
+
} else {
|
|
208
|
+
this.updateMoveable();
|
|
170
209
|
}
|
|
171
|
-
this.mode = getMode(el);
|
|
172
|
-
this.destroyDragEl();
|
|
173
|
-
this.destroyGhostEl();
|
|
174
|
-
this.dragEl = this.generateDragEl(el);
|
|
175
|
-
this.moveableOptions = await this.getOptions({
|
|
176
|
-
target: this.dragEl || this.target
|
|
177
|
-
});
|
|
178
|
-
this.initMoveable();
|
|
179
210
|
if (event) {
|
|
180
211
|
this.moveable?.dragStart(event);
|
|
181
212
|
}
|
|
182
213
|
}
|
|
183
|
-
|
|
214
|
+
updateMoveable(el = this.target) {
|
|
184
215
|
if (!this.moveable)
|
|
185
216
|
throw new Error("\u672A\u521D\u59CB\u5316moveable");
|
|
186
|
-
|
|
187
|
-
|
|
217
|
+
if (!el)
|
|
218
|
+
throw new Error("\u4E3A\u9009\u4E2D\u4EFB\u4F55\u8282\u70B9");
|
|
219
|
+
this.target = el;
|
|
220
|
+
this.init(el);
|
|
221
|
+
Object.entries(this.moveableOptions).forEach(([key, value]) => {
|
|
188
222
|
this.moveable[key] = value;
|
|
189
223
|
});
|
|
190
224
|
this.moveable.updateTarget();
|
|
@@ -192,15 +226,19 @@ class StageDragResize extends EventEmitter {
|
|
|
192
226
|
setGuidelines(type, guidelines) {
|
|
193
227
|
if (type === GuidesType.HORIZONTAL) {
|
|
194
228
|
this.horizontalGuidelines = guidelines;
|
|
229
|
+
this.moveableOptions.horizontalGuidelines = guidelines;
|
|
195
230
|
} else if (type === GuidesType.VERTICAL) {
|
|
196
231
|
this.verticalGuidelines = guidelines;
|
|
232
|
+
this.moveableOptions.verticalGuidelines = guidelines;
|
|
197
233
|
}
|
|
198
|
-
this.
|
|
234
|
+
this.updateMoveable();
|
|
199
235
|
}
|
|
200
236
|
clearGuides() {
|
|
201
|
-
this.verticalGuidelines = [];
|
|
202
237
|
this.horizontalGuidelines = [];
|
|
203
|
-
this.
|
|
238
|
+
this.verticalGuidelines = [];
|
|
239
|
+
this.moveableOptions.horizontalGuidelines = [];
|
|
240
|
+
this.moveableOptions.verticalGuidelines = [];
|
|
241
|
+
this.updateMoveable();
|
|
204
242
|
}
|
|
205
243
|
destroy() {
|
|
206
244
|
this.moveable?.destroy();
|
|
@@ -209,6 +247,37 @@ class StageDragResize extends EventEmitter {
|
|
|
209
247
|
this.dragStatus = "end" /* END */;
|
|
210
248
|
this.removeAllListeners();
|
|
211
249
|
}
|
|
250
|
+
init(el) {
|
|
251
|
+
if (/(auto|scroll)/.test(el.style.overflow)) {
|
|
252
|
+
el.style.overflow = "hidden";
|
|
253
|
+
}
|
|
254
|
+
this.mode = getMode(el);
|
|
255
|
+
this.destroyGhostEl();
|
|
256
|
+
this.updateDragEl(el);
|
|
257
|
+
this.moveableOptions = this.getOptions({
|
|
258
|
+
target: this.dragEl
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
setElementGuidelines(nodes) {
|
|
262
|
+
this.elementGuidelines.forEach((node) => {
|
|
263
|
+
node.remove();
|
|
264
|
+
});
|
|
265
|
+
this.elementGuidelines = [];
|
|
266
|
+
if (this.mode === Mode.ABSOLUTE) {
|
|
267
|
+
const frame = document.createDocumentFragment();
|
|
268
|
+
for (const node of nodes) {
|
|
269
|
+
const { width, height } = node.getBoundingClientRect();
|
|
270
|
+
if (node === this.target)
|
|
271
|
+
continue;
|
|
272
|
+
const { left, top } = getOffset(node);
|
|
273
|
+
const elementGuideline = document.createElement("div");
|
|
274
|
+
elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
|
|
275
|
+
this.elementGuidelines.push(elementGuideline);
|
|
276
|
+
frame.append(elementGuideline);
|
|
277
|
+
}
|
|
278
|
+
this.container.append(frame);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
212
281
|
initMoveable() {
|
|
213
282
|
this.moveable?.destroy();
|
|
214
283
|
this.moveable = new Moveable(this.container, {
|
|
@@ -216,35 +285,38 @@ class StageDragResize extends EventEmitter {
|
|
|
216
285
|
});
|
|
217
286
|
this.bindResizeEvent();
|
|
218
287
|
this.bindDragEvent();
|
|
288
|
+
this.bindRotateEvent();
|
|
289
|
+
this.bindScaleEvent();
|
|
219
290
|
}
|
|
220
291
|
bindResizeEvent() {
|
|
221
292
|
if (!this.moveable)
|
|
222
293
|
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
294
|
+
const frame = {
|
|
295
|
+
left: 0,
|
|
296
|
+
top: 0
|
|
297
|
+
};
|
|
223
298
|
this.moveable.on("resizeStart", (e) => {
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
299
|
+
if (!this.target)
|
|
300
|
+
return;
|
|
301
|
+
this.dragStatus = "start" /* START */;
|
|
302
|
+
this.moveableHelper?.onResizeStart(e);
|
|
303
|
+
frame.top = this.target.offsetTop;
|
|
304
|
+
frame.left = this.target.offsetLeft;
|
|
305
|
+
}).on("resize", (e) => {
|
|
306
|
+
const { width, height, drag } = e;
|
|
230
307
|
if (!this.moveable || !this.target || !this.dragEl)
|
|
231
308
|
return;
|
|
232
309
|
const { beforeTranslate } = drag;
|
|
233
310
|
this.dragStatus = "ing" /* ING */;
|
|
234
|
-
this.
|
|
235
|
-
this.target.style.height = `${height}px`;
|
|
236
|
-
this.dragEl.style.width = `${width}px`;
|
|
237
|
-
this.dragEl.style.height = `${height}px`;
|
|
311
|
+
this.moveableHelper?.onResize(e);
|
|
238
312
|
if (this.mode === Mode.SORTABLE) {
|
|
239
|
-
this.
|
|
240
|
-
|
|
241
|
-
|
|
313
|
+
this.target.style.top = "0px";
|
|
314
|
+
} else {
|
|
315
|
+
this.target.style.left = `${frame.left + beforeTranslate[0]}px`;
|
|
316
|
+
this.target.style.top = `${frame.top + beforeTranslate[1]}px`;
|
|
242
317
|
}
|
|
243
|
-
this.
|
|
244
|
-
this.
|
|
245
|
-
const offset = getAbsolutePosition(this.target, { left: beforeTranslate[0], top: beforeTranslate[1] });
|
|
246
|
-
this.target.style.left = `${offset.left}px`;
|
|
247
|
-
this.target.style.top = `${offset.top}px`;
|
|
318
|
+
this.target.style.width = `${width}px`;
|
|
319
|
+
this.target.style.height = `${height}px`;
|
|
248
320
|
}).on("resizeEnd", () => {
|
|
249
321
|
this.dragStatus = "end" /* END */;
|
|
250
322
|
this.update(true);
|
|
@@ -253,27 +325,31 @@ class StageDragResize extends EventEmitter {
|
|
|
253
325
|
bindDragEvent() {
|
|
254
326
|
if (!this.moveable)
|
|
255
327
|
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
256
|
-
|
|
328
|
+
const frame = {
|
|
329
|
+
left: 0,
|
|
330
|
+
top: 0
|
|
331
|
+
};
|
|
332
|
+
this.moveable.on("dragStart", (e) => {
|
|
257
333
|
if (!this.target)
|
|
258
334
|
throw new Error("\u672A\u9009\u4E2D\u7EC4\u4EF6");
|
|
259
335
|
this.dragStatus = "start" /* START */;
|
|
336
|
+
this.moveableHelper?.onDragStart(e);
|
|
260
337
|
if (this.mode === Mode.SORTABLE) {
|
|
261
338
|
this.ghostEl = this.generateGhostEl(this.target);
|
|
262
339
|
}
|
|
263
|
-
|
|
340
|
+
frame.top = this.target.offsetTop;
|
|
341
|
+
frame.left = this.target.offsetLeft;
|
|
342
|
+
}).on("drag", (e) => {
|
|
264
343
|
if (!this.target || !this.dragEl)
|
|
265
344
|
return;
|
|
266
345
|
this.dragStatus = "ing" /* ING */;
|
|
267
|
-
const offset = getAbsolutePosition(this.target, { left, top });
|
|
268
346
|
if (this.ghostEl) {
|
|
269
|
-
this.
|
|
270
|
-
this.ghostEl.style.top = `${offset.top}px`;
|
|
347
|
+
this.ghostEl.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
271
348
|
return;
|
|
272
349
|
}
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
275
|
-
this.target.style.
|
|
276
|
-
this.target.style.top = `${offset.top}px`;
|
|
350
|
+
this.moveableHelper?.onDrag(e);
|
|
351
|
+
this.target.style.left = `${frame.left + e.beforeTranslate[0]}px`;
|
|
352
|
+
this.target.style.top = `${frame.top + e.beforeTranslate[1]}px`;
|
|
277
353
|
}).on("dragEnd", () => {
|
|
278
354
|
if (this.dragStatus === "ing" /* ING */) {
|
|
279
355
|
switch (this.mode) {
|
|
@@ -288,13 +364,53 @@ class StageDragResize extends EventEmitter {
|
|
|
288
364
|
this.destroyGhostEl();
|
|
289
365
|
});
|
|
290
366
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
367
|
+
bindRotateEvent() {
|
|
368
|
+
if (!this.moveable)
|
|
369
|
+
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
370
|
+
this.moveable.on("rotateStart", (e) => {
|
|
371
|
+
this.dragStatus = "start" /* START */;
|
|
372
|
+
this.moveableHelper?.onRotateStart(e);
|
|
373
|
+
}).on("rotate", (e) => {
|
|
374
|
+
if (!this.target || !this.dragEl)
|
|
375
|
+
return;
|
|
376
|
+
this.dragStatus = "ing" /* ING */;
|
|
377
|
+
this.moveableHelper?.onRotate(e);
|
|
378
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
379
|
+
this.target.style.transform = frame?.toCSSObject().transform || "";
|
|
380
|
+
}).on("rotateEnd", (e) => {
|
|
381
|
+
this.dragStatus = "end" /* END */;
|
|
382
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
383
|
+
this.emit("update", {
|
|
384
|
+
el: this.target,
|
|
385
|
+
style: {
|
|
386
|
+
transform: frame?.get("transform")
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
bindScaleEvent() {
|
|
392
|
+
if (!this.moveable)
|
|
393
|
+
throw new Error("moveable \u4E3A\u521D\u59CB\u5316");
|
|
394
|
+
this.moveable.on("scaleStart", (e) => {
|
|
395
|
+
this.dragStatus = "start" /* START */;
|
|
396
|
+
this.moveableHelper?.onScaleStart(e);
|
|
397
|
+
}).on("scale", (e) => {
|
|
398
|
+
if (!this.target || !this.dragEl)
|
|
399
|
+
return;
|
|
400
|
+
this.dragStatus = "ing" /* ING */;
|
|
401
|
+
this.moveableHelper?.onScale(e);
|
|
402
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
403
|
+
this.target.style.transform = frame?.toCSSObject().transform || "";
|
|
404
|
+
}).on("scaleEnd", (e) => {
|
|
405
|
+
this.dragStatus = "end" /* END */;
|
|
406
|
+
const frame = this.moveableHelper?.getFrame(e.target);
|
|
407
|
+
this.emit("update", {
|
|
408
|
+
el: this.target,
|
|
409
|
+
style: {
|
|
410
|
+
transform: frame?.get("transform")
|
|
411
|
+
}
|
|
412
|
+
});
|
|
296
413
|
});
|
|
297
|
-
return getSnapElements(el).filter((element) => element !== this.target && !this.target?.contains(element));
|
|
298
414
|
}
|
|
299
415
|
sort() {
|
|
300
416
|
if (!this.target || !this.ghostEl)
|
|
@@ -316,12 +432,13 @@ class StageDragResize extends EventEmitter {
|
|
|
316
432
|
}
|
|
317
433
|
}
|
|
318
434
|
update(isResize = false) {
|
|
319
|
-
|
|
320
|
-
|
|
435
|
+
if (!this.target)
|
|
436
|
+
return;
|
|
437
|
+
const offset = this.mode === Mode.SORTABLE ? { left: 0, top: 0 } : { left: this.target.offsetLeft, top: this.target.offsetTop };
|
|
321
438
|
const left = this.calcValueByFontsize(offset.left);
|
|
322
439
|
const top = this.calcValueByFontsize(offset.top);
|
|
323
|
-
const width = this.calcValueByFontsize(
|
|
324
|
-
const height = this.calcValueByFontsize(
|
|
440
|
+
const width = this.calcValueByFontsize(this.target.clientWidth);
|
|
441
|
+
const height = this.calcValueByFontsize(this.target.clientHeight);
|
|
325
442
|
this.emit("update", {
|
|
326
443
|
el: this.target,
|
|
327
444
|
style: isResize ? { left, top, width, height } : { left, top }
|
|
@@ -333,8 +450,8 @@ class StageDragResize extends EventEmitter {
|
|
|
333
450
|
}
|
|
334
451
|
const ghostEl = el.cloneNode(true);
|
|
335
452
|
const { top, left } = getAbsolutePosition(el, getOffset(el));
|
|
336
|
-
ghostEl.id = `${GHOST_EL_ID_PREFIX}${
|
|
337
|
-
ghostEl.style.zIndex =
|
|
453
|
+
ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
|
|
454
|
+
ghostEl.style.zIndex = ZIndex.GHOST_EL;
|
|
338
455
|
ghostEl.style.opacity = ".5";
|
|
339
456
|
ghostEl.style.position = "absolute";
|
|
340
457
|
ghostEl.style.left = `${left}px`;
|
|
@@ -346,49 +463,73 @@ class StageDragResize extends EventEmitter {
|
|
|
346
463
|
this.ghostEl?.remove();
|
|
347
464
|
this.ghostEl = void 0;
|
|
348
465
|
}
|
|
349
|
-
|
|
350
|
-
if (this.dragEl) {
|
|
351
|
-
this.destroyDragEl();
|
|
352
|
-
}
|
|
353
|
-
const { width, height } = el.getBoundingClientRect();
|
|
466
|
+
updateDragEl(el) {
|
|
354
467
|
const offset = getOffset(el);
|
|
355
|
-
const
|
|
356
|
-
dragEl.style.cssText = `
|
|
468
|
+
const { transform } = getComputedStyle(el);
|
|
469
|
+
this.dragEl.style.cssText = `
|
|
357
470
|
position: absolute;
|
|
471
|
+
transform: ${transform};
|
|
358
472
|
left: ${offset.left}px;
|
|
359
473
|
top: ${offset.top}px;
|
|
360
|
-
width: ${
|
|
361
|
-
height: ${
|
|
474
|
+
width: ${el.clientWidth}px;
|
|
475
|
+
height: ${el.clientHeight}px;
|
|
476
|
+
z-index: ${ZIndex.DRAG_EL};
|
|
362
477
|
`;
|
|
363
|
-
this.
|
|
364
|
-
|
|
478
|
+
this.dragEl.id = `${DRAG_EL_ID_PREFIX}${el.id}`;
|
|
479
|
+
if (typeof this.core.config.updateDragEl === "function") {
|
|
480
|
+
this.core.config.updateDragEl(this.dragEl, el);
|
|
481
|
+
}
|
|
365
482
|
}
|
|
366
483
|
destroyDragEl() {
|
|
367
484
|
this.dragEl?.remove();
|
|
368
|
-
this.dragEl = void 0;
|
|
369
485
|
}
|
|
370
|
-
|
|
486
|
+
getOptions(options = {}) {
|
|
371
487
|
if (!this.target)
|
|
372
488
|
return {};
|
|
373
489
|
const isAbsolute = this.mode === Mode.ABSOLUTE;
|
|
490
|
+
const isFixed = this.mode === Mode.FIXED;
|
|
374
491
|
let { moveableOptions = {} } = this.core.config;
|
|
375
492
|
if (typeof moveableOptions === "function") {
|
|
376
493
|
moveableOptions = moveableOptions(this.core);
|
|
377
494
|
}
|
|
495
|
+
const elementGuidelines = moveableOptions.elementGuidelines || this.target.parentElement?.children || [];
|
|
496
|
+
this.setElementGuidelines(elementGuidelines);
|
|
497
|
+
if (moveableOptions.elementGuidelines) {
|
|
498
|
+
delete moveableOptions.elementGuidelines;
|
|
499
|
+
}
|
|
378
500
|
return {
|
|
379
|
-
|
|
380
|
-
|
|
501
|
+
origin: false,
|
|
502
|
+
rootContainer: this.core.container,
|
|
381
503
|
zoom: 1,
|
|
382
|
-
dragArea:
|
|
504
|
+
dragArea: false,
|
|
383
505
|
draggable: true,
|
|
384
506
|
resizable: true,
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
507
|
+
scalable: false,
|
|
508
|
+
rotatable: false,
|
|
509
|
+
snappable: isAbsolute || isFixed,
|
|
510
|
+
snapGap: isAbsolute || isFixed,
|
|
511
|
+
snapThreshold: 5,
|
|
512
|
+
snapDigit: 0,
|
|
513
|
+
throttleDrag: 0,
|
|
514
|
+
isDisplaySnapDigit: isAbsolute,
|
|
515
|
+
snapDirections: {
|
|
516
|
+
top: isAbsolute,
|
|
517
|
+
right: isAbsolute,
|
|
518
|
+
bottom: isAbsolute,
|
|
519
|
+
left: isAbsolute,
|
|
520
|
+
center: isAbsolute,
|
|
521
|
+
middle: isAbsolute
|
|
522
|
+
},
|
|
523
|
+
elementSnapDirections: {
|
|
524
|
+
top: isAbsolute,
|
|
525
|
+
right: isAbsolute,
|
|
526
|
+
bottom: isAbsolute,
|
|
527
|
+
left: isAbsolute
|
|
528
|
+
},
|
|
529
|
+
isDisplayInnerSnapDigit: true,
|
|
390
530
|
horizontalGuidelines: this.horizontalGuidelines,
|
|
391
531
|
verticalGuidelines: this.verticalGuidelines,
|
|
532
|
+
elementGuidelines: this.elementGuidelines,
|
|
392
533
|
bounds: {
|
|
393
534
|
top: 0,
|
|
394
535
|
left: 0,
|
|
@@ -457,18 +598,150 @@ const up = (deltaTop, target) => {
|
|
|
457
598
|
};
|
|
458
599
|
};
|
|
459
600
|
|
|
601
|
+
class TargetCalibrate extends EventEmitter {
|
|
602
|
+
constructor(config) {
|
|
603
|
+
super();
|
|
604
|
+
this.parent = config.parent;
|
|
605
|
+
this.mask = config.mask;
|
|
606
|
+
this.dr = config.dr;
|
|
607
|
+
this.core = config.core;
|
|
608
|
+
this.operationEl = globalThis.document.createElement("div");
|
|
609
|
+
this.parent.append(this.operationEl);
|
|
610
|
+
}
|
|
611
|
+
update(el, prefix) {
|
|
612
|
+
const { left, top } = this.getOffset(el);
|
|
613
|
+
const { transform } = getComputedStyle(el);
|
|
614
|
+
this.operationEl.style.cssText = `
|
|
615
|
+
position: absolute;
|
|
616
|
+
transform: ${transform};
|
|
617
|
+
left: ${left}px;
|
|
618
|
+
top: ${top}px;
|
|
619
|
+
width: ${el.clientWidth}px;
|
|
620
|
+
height: ${el.clientHeight}px;
|
|
621
|
+
`;
|
|
622
|
+
this.operationEl.id = `${prefix}${el.id}`;
|
|
623
|
+
if (typeof this.core.config.updateDragEl === "function") {
|
|
624
|
+
this.core.config.updateDragEl(this.operationEl, el);
|
|
625
|
+
}
|
|
626
|
+
return this.operationEl;
|
|
627
|
+
}
|
|
628
|
+
destroy() {
|
|
629
|
+
this.operationEl?.remove();
|
|
630
|
+
}
|
|
631
|
+
getOffset(el) {
|
|
632
|
+
const { offsetParent } = el;
|
|
633
|
+
const left = el.offsetLeft;
|
|
634
|
+
const top = el.offsetTop;
|
|
635
|
+
if (offsetParent) {
|
|
636
|
+
const parentOffset = this.getOffset(offsetParent);
|
|
637
|
+
return {
|
|
638
|
+
left: left + parentOffset.left,
|
|
639
|
+
top: top + parentOffset.top
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
if (this.dr.mode === Mode.FIXED) {
|
|
643
|
+
if (getMode(el) === Mode.FIXED) {
|
|
644
|
+
return {
|
|
645
|
+
left,
|
|
646
|
+
top
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
return {
|
|
650
|
+
left: left - this.mask.scrollLeft,
|
|
651
|
+
top: top - this.mask.scrollTop
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
if (getMode(el) === Mode.FIXED) {
|
|
655
|
+
return {
|
|
656
|
+
left: left + this.mask.scrollLeft,
|
|
657
|
+
top: top + this.mask.scrollTop
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
left,
|
|
662
|
+
top
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
class StageHighlight extends EventEmitter {
|
|
668
|
+
constructor(config) {
|
|
669
|
+
super();
|
|
670
|
+
this.core = config.core;
|
|
671
|
+
this.container = config.container;
|
|
672
|
+
this.calibrationTarget = new TargetCalibrate({
|
|
673
|
+
parent: this.core.mask.content,
|
|
674
|
+
mask: this.core.mask,
|
|
675
|
+
dr: this.core.dr,
|
|
676
|
+
core: this.core
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
highlight(el) {
|
|
680
|
+
if (!el || el === this.target)
|
|
681
|
+
return;
|
|
682
|
+
this.target = el;
|
|
683
|
+
this.moveable?.destroy();
|
|
684
|
+
this.moveable = new Moveable(this.container, {
|
|
685
|
+
target: this.calibrationTarget.update(el, HIGHLIGHT_EL_ID_PREFIX),
|
|
686
|
+
origin: false,
|
|
687
|
+
rootContainer: this.core.container,
|
|
688
|
+
zoom: 1
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
clearHighlight() {
|
|
692
|
+
if (!this.moveable)
|
|
693
|
+
return;
|
|
694
|
+
this.target = void 0;
|
|
695
|
+
this.moveable.target = null;
|
|
696
|
+
this.moveable.updateTarget();
|
|
697
|
+
}
|
|
698
|
+
destroy() {
|
|
699
|
+
this.moveable?.destroy();
|
|
700
|
+
this.calibrationTarget.destroy();
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
460
704
|
class Rule extends EventEmitter$1 {
|
|
461
|
-
hGuides;
|
|
462
|
-
vGuides;
|
|
463
|
-
horizontalGuidelines = [];
|
|
464
|
-
verticalGuidelines = [];
|
|
465
|
-
container;
|
|
466
|
-
containerResizeObserver;
|
|
467
705
|
constructor(container) {
|
|
468
706
|
super();
|
|
707
|
+
this.horizontalGuidelines = getGuideLineFromCache(GuidesType.HORIZONTAL);
|
|
708
|
+
this.verticalGuidelines = getGuideLineFromCache(GuidesType.VERTICAL);
|
|
709
|
+
this.getGuidesStyle = (type) => ({
|
|
710
|
+
position: "fixed",
|
|
711
|
+
zIndex: 1,
|
|
712
|
+
left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
|
|
713
|
+
top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
|
|
714
|
+
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
715
|
+
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
716
|
+
});
|
|
717
|
+
this.createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
718
|
+
type,
|
|
719
|
+
defaultGuides,
|
|
720
|
+
displayDragPos: true,
|
|
721
|
+
backgroundColor: "#fff",
|
|
722
|
+
lineColor: "#000",
|
|
723
|
+
textColor: "#000",
|
|
724
|
+
style: this.getGuidesStyle(type)
|
|
725
|
+
});
|
|
726
|
+
this.hGuidesChangeGuidesHandler = (e) => {
|
|
727
|
+
this.horizontalGuidelines = e.guides;
|
|
728
|
+
this.emit("changeGuides", {
|
|
729
|
+
type: GuidesType.HORIZONTAL,
|
|
730
|
+
guides: this.horizontalGuidelines
|
|
731
|
+
});
|
|
732
|
+
globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
|
|
733
|
+
};
|
|
734
|
+
this.vGuidesChangeGuidesHandler = (e) => {
|
|
735
|
+
this.verticalGuidelines = e.guides;
|
|
736
|
+
this.emit("changeGuides", {
|
|
737
|
+
type: GuidesType.VERTICAL,
|
|
738
|
+
guides: this.verticalGuidelines
|
|
739
|
+
});
|
|
740
|
+
globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, JSON.stringify(e.guides));
|
|
741
|
+
};
|
|
469
742
|
this.container = container;
|
|
470
|
-
this.hGuides = this.createGuides(GuidesType.HORIZONTAL);
|
|
471
|
-
this.vGuides = this.createGuides(GuidesType.VERTICAL);
|
|
743
|
+
this.hGuides = this.createGuides(GuidesType.HORIZONTAL, this.horizontalGuidelines);
|
|
744
|
+
this.vGuides = this.createGuides(GuidesType.VERTICAL, this.verticalGuidelines);
|
|
472
745
|
this.hGuides.on("changeGuides", this.hGuidesChangeGuidesHandler);
|
|
473
746
|
this.vGuides.on("changeGuides", this.vGuidesChangeGuidesHandler);
|
|
474
747
|
this.containerResizeObserver = new ResizeObserver(() => {
|
|
@@ -502,6 +775,8 @@ class Rule extends EventEmitter$1 {
|
|
|
502
775
|
type: GuidesType.HORIZONTAL,
|
|
503
776
|
guides: []
|
|
504
777
|
});
|
|
778
|
+
globalThis.localStorage.setItem(V_GUIDE_LINE_STORAGE_KEY, "[]");
|
|
779
|
+
globalThis.localStorage.setItem(H_GUIDE_LINE_STORAGE_KEY, "[]");
|
|
505
780
|
}
|
|
506
781
|
showRule(show = true) {
|
|
507
782
|
if (show) {
|
|
@@ -534,40 +809,10 @@ class Rule extends EventEmitter$1 {
|
|
|
534
809
|
this.containerResizeObserver.disconnect();
|
|
535
810
|
this.removeAllListeners();
|
|
536
811
|
}
|
|
537
|
-
getGuidesStyle = (type) => ({
|
|
538
|
-
position: "fixed",
|
|
539
|
-
zIndex: 1,
|
|
540
|
-
left: type === GuidesType.HORIZONTAL ? 0 : "-30px",
|
|
541
|
-
top: type === GuidesType.HORIZONTAL ? "-30px" : 0,
|
|
542
|
-
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
543
|
-
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
544
|
-
});
|
|
545
|
-
createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
546
|
-
type,
|
|
547
|
-
defaultGuides,
|
|
548
|
-
displayDragPos: true,
|
|
549
|
-
backgroundColor: "#fff",
|
|
550
|
-
lineColor: "#000",
|
|
551
|
-
textColor: "#000",
|
|
552
|
-
style: this.getGuidesStyle(type)
|
|
553
|
-
});
|
|
554
|
-
hGuidesChangeGuidesHandler = (e) => {
|
|
555
|
-
this.horizontalGuidelines = e.guides;
|
|
556
|
-
this.emit("changeGuides", {
|
|
557
|
-
type: GuidesType.HORIZONTAL,
|
|
558
|
-
guides: this.horizontalGuidelines
|
|
559
|
-
});
|
|
560
|
-
};
|
|
561
|
-
vGuidesChangeGuidesHandler = (e) => {
|
|
562
|
-
this.verticalGuidelines = e.guides;
|
|
563
|
-
this.emit("changeGuides", {
|
|
564
|
-
type: GuidesType.VERTICAL,
|
|
565
|
-
guides: this.verticalGuidelines
|
|
566
|
-
});
|
|
567
|
-
};
|
|
568
812
|
}
|
|
569
813
|
|
|
570
814
|
const wrapperClassName = "editor-mask-wrapper";
|
|
815
|
+
const throttleTime = 100;
|
|
571
816
|
const hideScrollbar = () => {
|
|
572
817
|
const style = globalThis.document.createElement("style");
|
|
573
818
|
style.innerHTML = `
|
|
@@ -601,28 +846,73 @@ const createWrapper = () => {
|
|
|
601
846
|
return el;
|
|
602
847
|
};
|
|
603
848
|
class StageMask extends Rule {
|
|
604
|
-
content = createContent();
|
|
605
|
-
wrapper;
|
|
606
|
-
core;
|
|
607
|
-
page = null;
|
|
608
|
-
pageScrollParent = null;
|
|
609
|
-
scrollTop = 0;
|
|
610
|
-
scrollLeft = 0;
|
|
611
|
-
width = 0;
|
|
612
|
-
height = 0;
|
|
613
|
-
wrapperHeight = 0;
|
|
614
|
-
wrapperWidth = 0;
|
|
615
|
-
mode = Mode.ABSOLUTE;
|
|
616
|
-
pageResizeObserver = null;
|
|
617
|
-
wrapperResizeObserver = null;
|
|
618
849
|
constructor(config) {
|
|
619
850
|
const wrapper = createWrapper();
|
|
620
851
|
super(wrapper);
|
|
852
|
+
this.content = createContent();
|
|
853
|
+
this.page = null;
|
|
854
|
+
this.pageScrollParent = null;
|
|
855
|
+
this.scrollTop = 0;
|
|
856
|
+
this.scrollLeft = 0;
|
|
857
|
+
this.width = 0;
|
|
858
|
+
this.height = 0;
|
|
859
|
+
this.wrapperHeight = 0;
|
|
860
|
+
this.wrapperWidth = 0;
|
|
861
|
+
this.maxScrollTop = 0;
|
|
862
|
+
this.maxScrollLeft = 0;
|
|
863
|
+
this.intersectionObserver = null;
|
|
864
|
+
this.mode = Mode.ABSOLUTE;
|
|
865
|
+
this.pageResizeObserver = null;
|
|
866
|
+
this.wrapperResizeObserver = null;
|
|
867
|
+
this.highlightHandler = throttle((event) => {
|
|
868
|
+
this.emit("highlight", event);
|
|
869
|
+
}, throttleTime);
|
|
870
|
+
this.mouseDownHandler = (event) => {
|
|
871
|
+
this.emit("clearHighlight");
|
|
872
|
+
event.stopImmediatePropagation();
|
|
873
|
+
event.stopPropagation();
|
|
874
|
+
if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT)
|
|
875
|
+
return;
|
|
876
|
+
if (event.target.className.indexOf("moveable-control") !== -1) {
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
this.content.removeEventListener("mousemove", this.highlightHandler);
|
|
880
|
+
this.emit("beforeSelect", event);
|
|
881
|
+
globalThis.document.addEventListener("mouseup", this.mouseUpHandler);
|
|
882
|
+
};
|
|
883
|
+
this.mouseUpHandler = () => {
|
|
884
|
+
globalThis.document.removeEventListener("mouseup", this.mouseUpHandler);
|
|
885
|
+
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
886
|
+
this.emit("select");
|
|
887
|
+
};
|
|
888
|
+
this.mouseWheelHandler = (event) => {
|
|
889
|
+
this.emit("clearHighlight");
|
|
890
|
+
if (!this.page)
|
|
891
|
+
throw new Error("page \u672A\u521D\u59CB\u5316");
|
|
892
|
+
const { deltaY, deltaX } = event;
|
|
893
|
+
if (this.page.clientHeight < this.wrapperHeight && deltaY)
|
|
894
|
+
return;
|
|
895
|
+
if (this.page.clientWidth < this.wrapperWidth && deltaX)
|
|
896
|
+
return;
|
|
897
|
+
if (this.maxScrollTop > 0) {
|
|
898
|
+
this.scrollTop = this.scrollTop + deltaY;
|
|
899
|
+
}
|
|
900
|
+
if (this.maxScrollLeft > 0) {
|
|
901
|
+
this.scrollLeft = this.scrollLeft + deltaX;
|
|
902
|
+
}
|
|
903
|
+
this.scroll();
|
|
904
|
+
this.emit("scroll", event);
|
|
905
|
+
};
|
|
906
|
+
this.mouseLeaveHandler = () => {
|
|
907
|
+
setTimeout(() => this.emit("clearHighlight"), throttleTime);
|
|
908
|
+
};
|
|
621
909
|
this.wrapper = wrapper;
|
|
622
910
|
this.core = config.core;
|
|
623
911
|
this.content.addEventListener("mousedown", this.mouseDownHandler);
|
|
624
912
|
this.wrapper.appendChild(this.content);
|
|
625
913
|
this.content.addEventListener("wheel", this.mouseWheelHandler);
|
|
914
|
+
this.content.addEventListener("mousemove", this.highlightHandler);
|
|
915
|
+
this.content.addEventListener("mouseleave", this.mouseLeaveHandler);
|
|
626
916
|
}
|
|
627
917
|
setMode(mode) {
|
|
628
918
|
this.mode = mode;
|
|
@@ -641,12 +931,33 @@ class StageMask extends Rule {
|
|
|
641
931
|
this.page = page;
|
|
642
932
|
this.pageScrollParent = getScrollParent(page) || this.core.renderer.contentWindow?.document.documentElement || null;
|
|
643
933
|
this.pageResizeObserver?.disconnect();
|
|
934
|
+
this.wrapperResizeObserver?.disconnect();
|
|
935
|
+
this.intersectionObserver?.disconnect();
|
|
936
|
+
if (typeof IntersectionObserver !== "undefined") {
|
|
937
|
+
this.intersectionObserver = new IntersectionObserver((entries) => {
|
|
938
|
+
entries.forEach((entry) => {
|
|
939
|
+
const { target, intersectionRatio } = entry;
|
|
940
|
+
if (intersectionRatio <= 0) {
|
|
941
|
+
this.scrollIntoView(target);
|
|
942
|
+
}
|
|
943
|
+
this.intersectionObserver?.unobserve(target);
|
|
944
|
+
});
|
|
945
|
+
}, {
|
|
946
|
+
root: this.pageScrollParent,
|
|
947
|
+
rootMargin: "0px",
|
|
948
|
+
threshold: 1
|
|
949
|
+
});
|
|
950
|
+
}
|
|
644
951
|
if (typeof ResizeObserver !== "undefined") {
|
|
645
952
|
this.pageResizeObserver = new ResizeObserver((entries) => {
|
|
646
953
|
const [entry] = entries;
|
|
647
954
|
const { clientHeight, clientWidth } = entry.target;
|
|
648
955
|
this.setHeight(clientHeight);
|
|
649
956
|
this.setWidth(clientWidth);
|
|
957
|
+
this.scroll();
|
|
958
|
+
if (this.core.dr.moveable) {
|
|
959
|
+
this.core.dr.updateMoveable();
|
|
960
|
+
}
|
|
650
961
|
});
|
|
651
962
|
this.pageResizeObserver.observe(page);
|
|
652
963
|
this.wrapperResizeObserver = new ResizeObserver((entries) => {
|
|
@@ -654,6 +965,8 @@ class StageMask extends Rule {
|
|
|
654
965
|
const { clientHeight, clientWidth } = entry.target;
|
|
655
966
|
this.wrapperHeight = clientHeight;
|
|
656
967
|
this.wrapperWidth = clientWidth;
|
|
968
|
+
this.setMaxScrollLeft();
|
|
969
|
+
this.setMaxScrollTop();
|
|
657
970
|
});
|
|
658
971
|
this.wrapperResizeObserver.observe(this.wrapper);
|
|
659
972
|
}
|
|
@@ -666,16 +979,32 @@ class StageMask extends Rule {
|
|
|
666
979
|
setLayout(el) {
|
|
667
980
|
this.setMode(isFixedParent(el) ? Mode.FIXED : Mode.ABSOLUTE);
|
|
668
981
|
}
|
|
982
|
+
scrollIntoView(el) {
|
|
983
|
+
el.scrollIntoView();
|
|
984
|
+
if (!this.pageScrollParent)
|
|
985
|
+
return;
|
|
986
|
+
this.scrollLeft = this.pageScrollParent.scrollLeft;
|
|
987
|
+
this.scrollTop = this.pageScrollParent.scrollTop;
|
|
988
|
+
this.scroll();
|
|
989
|
+
}
|
|
669
990
|
destroy() {
|
|
670
991
|
this.content?.remove();
|
|
671
992
|
this.page = null;
|
|
672
993
|
this.pageScrollParent = null;
|
|
673
994
|
this.pageResizeObserver?.disconnect();
|
|
674
995
|
this.wrapperResizeObserver?.disconnect();
|
|
996
|
+
this.content.removeEventListener("mouseleave", this.mouseLeaveHandler);
|
|
675
997
|
super.destroy();
|
|
676
998
|
}
|
|
677
999
|
scroll() {
|
|
1000
|
+
this.fixScrollValue();
|
|
678
1001
|
let { scrollLeft, scrollTop } = this;
|
|
1002
|
+
if (this.pageScrollParent) {
|
|
1003
|
+
this.pageScrollParent.scrollTo({
|
|
1004
|
+
top: scrollTop,
|
|
1005
|
+
left: scrollLeft
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
679
1008
|
if (this.mode === Mode.FIXED) {
|
|
680
1009
|
scrollLeft = 0;
|
|
681
1010
|
scrollTop = 0;
|
|
@@ -688,71 +1017,65 @@ class StageMask extends Rule {
|
|
|
688
1017
|
}
|
|
689
1018
|
setHeight(height) {
|
|
690
1019
|
this.height = height;
|
|
1020
|
+
this.setMaxScrollTop();
|
|
691
1021
|
this.content.style.height = `${height}px`;
|
|
692
1022
|
}
|
|
693
1023
|
setWidth(width) {
|
|
694
1024
|
this.width = width;
|
|
1025
|
+
this.setMaxScrollLeft();
|
|
695
1026
|
this.content.style.width = `${width}px`;
|
|
696
1027
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
this.
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (!this.page)
|
|
714
|
-
throw new Error("page \u672A\u521D\u59CB\u5316");
|
|
715
|
-
const { deltaY, deltaX } = event;
|
|
716
|
-
const { height, wrapperHeight, width, wrapperWidth } = this;
|
|
717
|
-
const maxScrollTop = height - wrapperHeight;
|
|
718
|
-
const maxScrollLeft = width - wrapperWidth;
|
|
719
|
-
if (maxScrollTop > 0) {
|
|
720
|
-
if (deltaY > 0) {
|
|
721
|
-
this.scrollTop = this.scrollTop + Math.min(maxScrollTop - this.scrollTop, deltaY);
|
|
722
|
-
} else {
|
|
723
|
-
this.scrollTop = Math.max(this.scrollTop + deltaY, 0);
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (width > wrapperWidth) {
|
|
727
|
-
if (deltaX > 0) {
|
|
728
|
-
this.scrollLeft = this.scrollLeft + Math.min(maxScrollLeft - this.scrollLeft, deltaX);
|
|
729
|
-
} else {
|
|
730
|
-
this.scrollLeft = Math.max(this.scrollLeft + deltaX, 0);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
if (this.mode !== Mode.FIXED) {
|
|
734
|
-
this.scrollTo(this.scrollLeft, this.scrollTop);
|
|
735
|
-
}
|
|
736
|
-
if (this.pageScrollParent) {
|
|
737
|
-
this.pageScrollParent.scrollTo({
|
|
738
|
-
top: this.scrollTop,
|
|
739
|
-
left: this.scrollLeft
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
this.scroll();
|
|
743
|
-
this.emit("scroll", event);
|
|
744
|
-
};
|
|
1028
|
+
setMaxScrollLeft() {
|
|
1029
|
+
this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
|
|
1030
|
+
}
|
|
1031
|
+
setMaxScrollTop() {
|
|
1032
|
+
this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
|
|
1033
|
+
}
|
|
1034
|
+
fixScrollValue() {
|
|
1035
|
+
if (this.scrollTop < 0)
|
|
1036
|
+
this.scrollTop = 0;
|
|
1037
|
+
if (this.scrollLeft < 0)
|
|
1038
|
+
this.scrollLeft = 0;
|
|
1039
|
+
if (this.maxScrollTop < this.scrollTop)
|
|
1040
|
+
this.scrollTop = this.maxScrollTop;
|
|
1041
|
+
if (this.maxScrollLeft < this.scrollLeft)
|
|
1042
|
+
this.scrollLeft = this.maxScrollLeft;
|
|
1043
|
+
}
|
|
745
1044
|
}
|
|
746
1045
|
|
|
747
1046
|
class StageRender extends EventEmitter {
|
|
748
|
-
contentWindow = null;
|
|
749
|
-
runtime = null;
|
|
750
|
-
iframe;
|
|
751
|
-
runtimeUrl;
|
|
752
|
-
core;
|
|
753
|
-
render;
|
|
754
1047
|
constructor({ core }) {
|
|
755
1048
|
super();
|
|
1049
|
+
this.contentWindow = null;
|
|
1050
|
+
this.runtime = null;
|
|
1051
|
+
this.getMagicApi = () => ({
|
|
1052
|
+
onPageElUpdate: (el) => this.emit("page-el-update", el),
|
|
1053
|
+
onRuntimeReady: (runtime) => {
|
|
1054
|
+
this.runtime = runtime;
|
|
1055
|
+
globalThis.runtime = runtime;
|
|
1056
|
+
this.emit("runtime-ready", runtime);
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
this.getRuntime = () => {
|
|
1060
|
+
if (this.runtime)
|
|
1061
|
+
return Promise.resolve(this.runtime);
|
|
1062
|
+
return new Promise((resolve) => {
|
|
1063
|
+
const listener = (runtime) => {
|
|
1064
|
+
this.off("runtime-ready", listener);
|
|
1065
|
+
resolve(runtime);
|
|
1066
|
+
};
|
|
1067
|
+
this.on("runtime-ready", listener);
|
|
1068
|
+
});
|
|
1069
|
+
};
|
|
1070
|
+
this.loadHandler = async () => {
|
|
1071
|
+
this.emit("onload");
|
|
1072
|
+
if (this.render) {
|
|
1073
|
+
const el = await this.render(this.core);
|
|
1074
|
+
if (el) {
|
|
1075
|
+
this.iframe?.contentDocument?.body?.appendChild(el);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
756
1079
|
this.core = core;
|
|
757
1080
|
this.runtimeUrl = core.config.runtimeUrl || "";
|
|
758
1081
|
this.render = core.config.render;
|
|
@@ -765,14 +1088,6 @@ class StageRender extends EventEmitter {
|
|
|
765
1088
|
`;
|
|
766
1089
|
this.iframe.addEventListener("load", this.loadHandler);
|
|
767
1090
|
}
|
|
768
|
-
getMagicApi = () => ({
|
|
769
|
-
onPageElUpdate: (el) => this.emit("page-el-update", el),
|
|
770
|
-
onRuntimeReady: (runtime) => {
|
|
771
|
-
this.runtime = runtime;
|
|
772
|
-
globalThis.runtime = runtime;
|
|
773
|
-
this.emit("runtime-ready", runtime);
|
|
774
|
-
}
|
|
775
|
-
});
|
|
776
1091
|
async mount(el) {
|
|
777
1092
|
if (this.iframe) {
|
|
778
1093
|
if (!isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
|
|
@@ -789,17 +1104,6 @@ class StageRender extends EventEmitter {
|
|
|
789
1104
|
throw Error("mount \u5931\u8D25");
|
|
790
1105
|
}
|
|
791
1106
|
}
|
|
792
|
-
getRuntime = () => {
|
|
793
|
-
if (this.runtime)
|
|
794
|
-
return Promise.resolve(this.runtime);
|
|
795
|
-
return new Promise((resolve) => {
|
|
796
|
-
const listener = (runtime) => {
|
|
797
|
-
this.off("runtime-ready", listener);
|
|
798
|
-
resolve(runtime);
|
|
799
|
-
};
|
|
800
|
-
this.on("runtime-ready", listener);
|
|
801
|
-
});
|
|
802
|
-
};
|
|
803
1107
|
destroy() {
|
|
804
1108
|
this.iframe?.removeEventListener("load", this.loadHandler);
|
|
805
1109
|
this.contentWindow = null;
|
|
@@ -807,35 +1111,25 @@ class StageRender extends EventEmitter {
|
|
|
807
1111
|
this.iframe = void 0;
|
|
808
1112
|
this.removeAllListeners();
|
|
809
1113
|
}
|
|
810
|
-
loadHandler = async () => {
|
|
811
|
-
this.emit("onload");
|
|
812
|
-
if (this.render) {
|
|
813
|
-
const el = await this.render(this.core);
|
|
814
|
-
if (el) {
|
|
815
|
-
this.iframe?.contentDocument?.body?.appendChild(el);
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
};
|
|
819
1114
|
}
|
|
820
1115
|
|
|
821
1116
|
class StageCore extends EventEmitter {
|
|
822
|
-
selectedDom;
|
|
823
|
-
renderer;
|
|
824
|
-
mask;
|
|
825
|
-
dr;
|
|
826
|
-
config;
|
|
827
|
-
zoom = DEFAULT_ZOOM;
|
|
828
|
-
canSelect;
|
|
829
1117
|
constructor(config) {
|
|
830
1118
|
super();
|
|
1119
|
+
this.zoom = DEFAULT_ZOOM;
|
|
831
1120
|
this.config = config;
|
|
832
1121
|
this.setZoom(config.zoom);
|
|
833
1122
|
this.canSelect = config.canSelect || ((el) => !!el.id);
|
|
834
1123
|
this.renderer = new StageRender({ core: this });
|
|
835
1124
|
this.mask = new StageMask({ core: this });
|
|
836
1125
|
this.dr = new StageDragResize({ core: this, container: this.mask.content });
|
|
837
|
-
this.
|
|
838
|
-
this.renderer.on("
|
|
1126
|
+
this.highlightLayer = new StageHighlight({ core: this, container: this.mask.wrapper });
|
|
1127
|
+
this.renderer.on("runtime-ready", (runtime) => {
|
|
1128
|
+
this.emit("runtime-ready", runtime);
|
|
1129
|
+
});
|
|
1130
|
+
this.renderer.on("page-el-update", (el) => {
|
|
1131
|
+
this.mask?.observe(el);
|
|
1132
|
+
});
|
|
839
1133
|
this.mask.on("beforeSelect", (event) => {
|
|
840
1134
|
this.setElementFromPoint(event);
|
|
841
1135
|
}).on("select", () => {
|
|
@@ -843,6 +1137,16 @@ class StageCore extends EventEmitter {
|
|
|
843
1137
|
}).on("changeGuides", (data) => {
|
|
844
1138
|
this.dr.setGuidelines(data.type, data.guides);
|
|
845
1139
|
this.emit("changeGuides", data);
|
|
1140
|
+
}).on("highlight", async (event) => {
|
|
1141
|
+
await this.setElementFromPoint(event);
|
|
1142
|
+
if (this.highlightedDom === this.selectedDom) {
|
|
1143
|
+
this.highlightLayer.clearHighlight();
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
this.highlightLayer.highlight(this.highlightedDom);
|
|
1147
|
+
this.emit("highlight", this.highlightedDom);
|
|
1148
|
+
}).on("clearHighlight", async () => {
|
|
1149
|
+
this.highlightLayer.clearHighlight();
|
|
846
1150
|
});
|
|
847
1151
|
this.dr.on("update", (data) => {
|
|
848
1152
|
setTimeout(() => this.emit("update", data));
|
|
@@ -866,60 +1170,81 @@ class StageCore extends EventEmitter {
|
|
|
866
1170
|
let stopped = false;
|
|
867
1171
|
const stop = () => stopped = true;
|
|
868
1172
|
for (const el of els) {
|
|
869
|
-
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, stop)) {
|
|
1173
|
+
if (!el.id.startsWith(GHOST_EL_ID_PREFIX) && await this.canSelect(el, event, stop)) {
|
|
870
1174
|
if (stopped)
|
|
871
1175
|
break;
|
|
1176
|
+
if (event.type === "mousemove") {
|
|
1177
|
+
this.highlight(el);
|
|
1178
|
+
break;
|
|
1179
|
+
}
|
|
872
1180
|
this.select(el, event);
|
|
873
1181
|
break;
|
|
874
1182
|
}
|
|
875
1183
|
}
|
|
876
1184
|
}
|
|
877
1185
|
async select(idOrEl, event) {
|
|
878
|
-
|
|
879
|
-
if (typeof idOrEl === "string" || typeof idOrEl === "number") {
|
|
880
|
-
const runtime2 = await this.renderer?.getRuntime();
|
|
881
|
-
el = await runtime2?.select?.(`${idOrEl}`);
|
|
882
|
-
if (!el)
|
|
883
|
-
throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
|
|
884
|
-
} else {
|
|
885
|
-
el = idOrEl;
|
|
886
|
-
}
|
|
1186
|
+
const el = await this.getTargetElement(idOrEl);
|
|
887
1187
|
if (el === this.selectedDom)
|
|
888
1188
|
return;
|
|
889
|
-
const runtime = await this.renderer
|
|
1189
|
+
const runtime = await this.renderer.getRuntime();
|
|
1190
|
+
await runtime?.select?.(el.id);
|
|
890
1191
|
if (runtime?.beforeSelect) {
|
|
891
1192
|
await runtime.beforeSelect(el);
|
|
892
1193
|
}
|
|
893
1194
|
this.mask.setLayout(el);
|
|
894
|
-
this.dr
|
|
1195
|
+
this.dr.select(el, event);
|
|
1196
|
+
if (this.config.autoScrollIntoView || el.dataset.autoScrollIntoView) {
|
|
1197
|
+
this.mask.intersectionObserver?.observe(el);
|
|
1198
|
+
}
|
|
895
1199
|
this.selectedDom = el;
|
|
1200
|
+
if (this.renderer.contentWindow) {
|
|
1201
|
+
removeSelectedClassName(this.renderer.contentWindow.document);
|
|
1202
|
+
if (this.selectedDom) {
|
|
1203
|
+
addSelectedClassName(this.selectedDom, this.renderer.contentWindow.document);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
896
1206
|
}
|
|
897
1207
|
update(data) {
|
|
898
1208
|
const { config } = data;
|
|
899
|
-
this.renderer?.getRuntime().then((runtime) => {
|
|
1209
|
+
return this.renderer?.getRuntime().then((runtime) => {
|
|
900
1210
|
runtime?.update?.(data);
|
|
901
1211
|
setTimeout(() => {
|
|
902
1212
|
const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
|
|
903
|
-
if (el) {
|
|
1213
|
+
if (el && el.id === this.selectedDom?.id) {
|
|
1214
|
+
this.selectedDom = el;
|
|
904
1215
|
this.mask.setLayout(el);
|
|
905
|
-
this.dr
|
|
1216
|
+
this.dr.updateMoveable(el);
|
|
906
1217
|
}
|
|
907
1218
|
}, 0);
|
|
908
1219
|
});
|
|
909
1220
|
}
|
|
1221
|
+
async highlight(idOrEl) {
|
|
1222
|
+
let el;
|
|
1223
|
+
try {
|
|
1224
|
+
el = await this.getTargetElement(idOrEl);
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
this.highlightLayer.clearHighlight();
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
if (el === this.highlightedDom)
|
|
1230
|
+
return;
|
|
1231
|
+
this.highlightLayer.highlight(el);
|
|
1232
|
+
this.highlightedDom = el;
|
|
1233
|
+
}
|
|
910
1234
|
sortNode(data) {
|
|
911
|
-
this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
|
|
1235
|
+
return this.renderer?.getRuntime().then((runtime) => runtime?.sortNode?.(data));
|
|
912
1236
|
}
|
|
913
1237
|
add(data) {
|
|
914
|
-
this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
|
|
1238
|
+
return this.renderer?.getRuntime().then((runtime) => runtime?.add?.(data));
|
|
915
1239
|
}
|
|
916
1240
|
remove(data) {
|
|
917
|
-
this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
|
|
1241
|
+
return this.renderer?.getRuntime().then((runtime) => runtime?.remove?.(data));
|
|
918
1242
|
}
|
|
919
1243
|
setZoom(zoom = DEFAULT_ZOOM) {
|
|
920
1244
|
this.zoom = zoom;
|
|
921
1245
|
}
|
|
922
1246
|
mount(el) {
|
|
1247
|
+
this.container = el;
|
|
923
1248
|
const { mask, renderer } = this;
|
|
924
1249
|
renderer.mount(el);
|
|
925
1250
|
mask.mount(el);
|
|
@@ -930,11 +1255,22 @@ class StageCore extends EventEmitter {
|
|
|
930
1255
|
this.dr.clearGuides();
|
|
931
1256
|
}
|
|
932
1257
|
destroy() {
|
|
933
|
-
const { mask, renderer, dr } = this;
|
|
1258
|
+
const { mask, renderer, dr, highlightLayer } = this;
|
|
934
1259
|
renderer.destroy();
|
|
935
1260
|
mask.destroy();
|
|
936
1261
|
dr.destroy();
|
|
1262
|
+
highlightLayer.destroy();
|
|
937
1263
|
this.removeAllListeners();
|
|
1264
|
+
this.container = void 0;
|
|
1265
|
+
}
|
|
1266
|
+
async getTargetElement(idOrEl) {
|
|
1267
|
+
if (typeof idOrEl === "string" || typeof idOrEl === "number") {
|
|
1268
|
+
const el = this.renderer.contentWindow?.document.getElementById(`${idOrEl}`);
|
|
1269
|
+
if (!el)
|
|
1270
|
+
throw new Error(`\u4E0D\u5B58\u5728ID\u4E3A${idOrEl}\u7684\u5143\u7D20`);
|
|
1271
|
+
return el;
|
|
1272
|
+
}
|
|
1273
|
+
return idOrEl;
|
|
938
1274
|
}
|
|
939
1275
|
}
|
|
940
1276
|
|