@tmagic/stage 1.7.6 → 1.7.8-beta.1
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/LICENSE +235 -164
- package/dist/es/ActionManager.js +470 -0
- package/dist/es/DragResizeHelper.js +280 -0
- package/dist/es/MoveableActionsAble.js +64 -0
- package/dist/es/MoveableOptionsManager.js +204 -0
- package/dist/es/Rule.js +139 -0
- package/dist/es/StageCore.js +307 -0
- package/dist/es/StageDragResize.js +233 -0
- package/dist/es/StageHighlight.js +62 -0
- package/dist/es/StageMask.js +256 -0
- package/dist/es/StageMultiDragResize.js +153 -0
- package/dist/es/StageRender.js +186 -0
- package/dist/es/TargetShadow.js +68 -0
- package/dist/es/const.js +91 -0
- package/dist/es/index.js +12 -0
- package/dist/es/moveable-able.js +4 -0
- package/dist/es/style.js +4 -0
- package/dist/es/util.js +192 -0
- package/dist/tmagic-stage.umd.cjs +4811 -5308
- package/package.json +5 -4
- package/types/index.d.ts +857 -841
- package/dist/tmagic-stage.js +0 -2833
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import { AbleActionEventType, ContainerHighlightType, MouseButton, SelectStatus, StageDragStatus } from "./const.js";
|
|
2
|
+
import { isMoveableButton } from "./util.js";
|
|
3
|
+
import DragResizeHelper from "./DragResizeHelper.js";
|
|
4
|
+
import StageDragResize from "./StageDragResize.js";
|
|
5
|
+
import StageHighlight from "./StageHighlight.js";
|
|
6
|
+
import StageMultiDragResize from "./StageMultiDragResize.js";
|
|
7
|
+
import EventEmitter$1 from "events";
|
|
8
|
+
import { Env, addClassName, getDocument, getIdFromEl, removeClassNameByClassName } from "@tmagic/core";
|
|
9
|
+
import KeyController from "keycon";
|
|
10
|
+
import { throttle } from "lodash-es";
|
|
11
|
+
//#region packages/stage/src/ActionManager.ts
|
|
12
|
+
var throttleTime = 100;
|
|
13
|
+
var defaultContainerHighlightDuration = 800;
|
|
14
|
+
/**
|
|
15
|
+
* 管理蒙层mask之上的操作:1、监听键盘鼠标事件,判断形成单选、多选、高亮操作;2、管理单选、多选、高亮三个类协同工作。
|
|
16
|
+
* @extends EventEmitter
|
|
17
|
+
*/
|
|
18
|
+
var ActionManager = class extends EventEmitter$1 {
|
|
19
|
+
dr = null;
|
|
20
|
+
multiDr = null;
|
|
21
|
+
highlightLayer = null;
|
|
22
|
+
/** 单选、多选、高亮的容器(蒙层的content) */
|
|
23
|
+
container;
|
|
24
|
+
/** 当前选中的节点 */
|
|
25
|
+
selectedEl = null;
|
|
26
|
+
/** 多选选中的节点组 */
|
|
27
|
+
selectedElList = [];
|
|
28
|
+
/** 当前高亮的节点 */
|
|
29
|
+
highlightedEl;
|
|
30
|
+
/** 当前是否处于多选状态 */
|
|
31
|
+
isMultiSelectStatus = false;
|
|
32
|
+
/** 当拖拽组件到容器上方进入可加入容器状态时,给容器添加的一个class名称 */
|
|
33
|
+
containerHighlightClassName;
|
|
34
|
+
/** 当拖拽组件到容器上方时,需要悬停多久才能将组件加入容器 */
|
|
35
|
+
containerHighlightDuration;
|
|
36
|
+
/** 将组件加入容器的操作方式 */
|
|
37
|
+
containerHighlightType;
|
|
38
|
+
isAltKeydown = false;
|
|
39
|
+
getTargetElement;
|
|
40
|
+
getElementsFromPoint;
|
|
41
|
+
canSelect;
|
|
42
|
+
isContainer;
|
|
43
|
+
getRenderDocument;
|
|
44
|
+
disabledMultiSelect = false;
|
|
45
|
+
config;
|
|
46
|
+
mouseMoveHandler = throttle((event) => {
|
|
47
|
+
const handler = async () => {
|
|
48
|
+
if (event.target?.classList?.contains("moveable-direction")) return;
|
|
49
|
+
const el = await this.getElementFromPoint(event);
|
|
50
|
+
const id = getIdFromEl()(el);
|
|
51
|
+
if (!id) {
|
|
52
|
+
this.clearHighlight();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
this.emit("mousemove", event);
|
|
56
|
+
this.highlight(id);
|
|
57
|
+
};
|
|
58
|
+
handler();
|
|
59
|
+
}, throttleTime);
|
|
60
|
+
constructor(config) {
|
|
61
|
+
super();
|
|
62
|
+
this.config = config;
|
|
63
|
+
this.container = config.container;
|
|
64
|
+
this.containerHighlightClassName = config.containerHighlightClassName || "tmagic-stage-container-highlight";
|
|
65
|
+
this.containerHighlightDuration = config.containerHighlightDuration || defaultContainerHighlightDuration;
|
|
66
|
+
this.containerHighlightType = config.containerHighlightType;
|
|
67
|
+
this.disabledMultiSelect = config.disabledMultiSelect ?? false;
|
|
68
|
+
this.getTargetElement = config.getTargetElement;
|
|
69
|
+
this.getElementsFromPoint = config.getElementsFromPoint;
|
|
70
|
+
this.canSelect = config.canSelect || ((el) => Boolean(getIdFromEl()(el)));
|
|
71
|
+
this.getRenderDocument = config.getRenderDocument;
|
|
72
|
+
this.isContainer = config.isContainer;
|
|
73
|
+
this.dr = this.createDr(config);
|
|
74
|
+
if (!this.disabledMultiSelect) this.multiDr = this.createMultiDr(config);
|
|
75
|
+
this.highlightLayer = new StageHighlight({
|
|
76
|
+
container: config.container,
|
|
77
|
+
updateDragEl: config.updateDragEl,
|
|
78
|
+
getRootContainer: config.getRootContainer
|
|
79
|
+
});
|
|
80
|
+
this.initMouseEvent();
|
|
81
|
+
this.initKeyEvent();
|
|
82
|
+
}
|
|
83
|
+
disableMultiSelect() {
|
|
84
|
+
this.disabledMultiSelect = true;
|
|
85
|
+
if (this.multiDr) {
|
|
86
|
+
this.multiDr.destroy();
|
|
87
|
+
this.multiDr = null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
enableMultiSelect() {
|
|
91
|
+
this.disabledMultiSelect = false;
|
|
92
|
+
if (!this.multiDr) this.multiDr = this.createMultiDr(this.config);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* 设置水平/垂直参考线
|
|
96
|
+
* @param type 参考线类型
|
|
97
|
+
* @param guidelines 参考线坐标数组
|
|
98
|
+
*/
|
|
99
|
+
setGuidelines(type, guidelines) {
|
|
100
|
+
this.dr?.setGuidelines(type, guidelines);
|
|
101
|
+
this.multiDr?.setGuidelines(type, guidelines);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 清空所有参考线
|
|
105
|
+
*/
|
|
106
|
+
clearGuides() {
|
|
107
|
+
this.dr?.clearGuides();
|
|
108
|
+
this.multiDr?.clearGuides();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 更新moveable,外部主要调用场景是元素配置变更、页面大小变更
|
|
112
|
+
* @param el 变更的元素
|
|
113
|
+
*/
|
|
114
|
+
updateMoveable(el) {
|
|
115
|
+
this.dr?.updateMoveable(el);
|
|
116
|
+
this.multiDr?.updateMoveable();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 判断是否单选选中的元素
|
|
120
|
+
*/
|
|
121
|
+
isSelectedEl(el) {
|
|
122
|
+
return getIdFromEl()(el) === getIdFromEl()(this.selectedEl);
|
|
123
|
+
}
|
|
124
|
+
setSelectedEl(el) {
|
|
125
|
+
this.selectedEl = el;
|
|
126
|
+
}
|
|
127
|
+
getSelectedEl() {
|
|
128
|
+
return this.selectedEl;
|
|
129
|
+
}
|
|
130
|
+
getSelectedElList() {
|
|
131
|
+
return this.selectedElList;
|
|
132
|
+
}
|
|
133
|
+
getMoveableOption(key) {
|
|
134
|
+
if (this.dr?.getTarget()) return this.dr.getOption(key);
|
|
135
|
+
if (this.multiDr?.targetList.length) return this.multiDr.getOption(key);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* 获取鼠标下方第一个可选中元素,如果元素层叠,返回到是最上层元素
|
|
139
|
+
* @param event 鼠标事件
|
|
140
|
+
* @returns 鼠标下方第一个可选中元素
|
|
141
|
+
*/
|
|
142
|
+
async getElementFromPoint(event) {
|
|
143
|
+
const els = this.getElementsFromPoint(event);
|
|
144
|
+
this.emit("get-elements-from-point", els);
|
|
145
|
+
let stopped = false;
|
|
146
|
+
const stop = () => stopped = true;
|
|
147
|
+
for (const el of els) if (!getIdFromEl()(el)?.startsWith("ghost_el_") && await this.isElCanSelect(el, event, stop)) {
|
|
148
|
+
if (stopped) break;
|
|
149
|
+
return el;
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 判断一个元素能否在当前场景被选中
|
|
155
|
+
* @param el 被判断的元素
|
|
156
|
+
* @param event 鼠标事件
|
|
157
|
+
* @param stop 通过该元素如果得知剩下的元素都不可被选中,通知调用方终止对剩下元素的判断
|
|
158
|
+
* @returns 能否选中
|
|
159
|
+
*/
|
|
160
|
+
async isElCanSelect(el, event, stop) {
|
|
161
|
+
if (!await this.canSelect(el, event, stop)) return false;
|
|
162
|
+
if (this.isMultiSelectStatus) return this.canMultiSelect(el, stop);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* 判断一个元素是否可以被多选,如果当前元素是page,则调stop函数告诉调用方不必继续判断其它元素了
|
|
167
|
+
*/
|
|
168
|
+
canMultiSelect(el, stop) {
|
|
169
|
+
if (el.className.includes("magic-ui-page")) {
|
|
170
|
+
stop();
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
const selectedEl = this.getSelectedEl();
|
|
174
|
+
if (selectedEl?.className.includes("magic-ui-page")) return true;
|
|
175
|
+
return this.multiDr?.canSelect(el, selectedEl) || false;
|
|
176
|
+
}
|
|
177
|
+
select(el, event) {
|
|
178
|
+
this.setSelectedEl(el);
|
|
179
|
+
this.clearSelectStatus(SelectStatus.MULTI_SELECT);
|
|
180
|
+
this.dr?.select(el, event);
|
|
181
|
+
}
|
|
182
|
+
multiSelect(ids) {
|
|
183
|
+
this.selectedElList = [];
|
|
184
|
+
ids.forEach((id) => {
|
|
185
|
+
const el = this.getTargetElement(id);
|
|
186
|
+
if (el) this.selectedElList.push(el);
|
|
187
|
+
});
|
|
188
|
+
this.clearSelectStatus(SelectStatus.SELECT);
|
|
189
|
+
this.multiDr?.multiSelect(this.selectedElList);
|
|
190
|
+
}
|
|
191
|
+
getHighlightEl() {
|
|
192
|
+
return this.highlightedEl;
|
|
193
|
+
}
|
|
194
|
+
setHighlightEl(el) {
|
|
195
|
+
this.highlightedEl = el;
|
|
196
|
+
}
|
|
197
|
+
highlight(id) {
|
|
198
|
+
let el;
|
|
199
|
+
try {
|
|
200
|
+
el = this.getTargetElement(id);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
this.clearHighlight();
|
|
203
|
+
console.warn("getTargetElement error:", error);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (el === this.getSelectedEl() || this.multiDr?.dragStatus === StageDragStatus.ING) {
|
|
207
|
+
this.clearHighlight();
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (el === this.highlightedEl || !el) return;
|
|
211
|
+
this.highlightLayer?.highlight(el);
|
|
212
|
+
this.highlightedEl = el;
|
|
213
|
+
this.emit("highlight", el);
|
|
214
|
+
}
|
|
215
|
+
clearHighlight() {
|
|
216
|
+
this.setHighlightEl(void 0);
|
|
217
|
+
this.highlightLayer?.clearHighlight();
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* 用于在切换选择模式时清除上一次的状态
|
|
221
|
+
* @param selectType 需要清理的选择模式
|
|
222
|
+
*/
|
|
223
|
+
clearSelectStatus(selectType) {
|
|
224
|
+
if (selectType === SelectStatus.MULTI_SELECT) {
|
|
225
|
+
this.multiDr?.clearSelectStatus();
|
|
226
|
+
this.selectedElList = [];
|
|
227
|
+
} else this.dr?.clearSelectStatus();
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* 找到鼠标下方的容器,通过添加className对容器进行标记
|
|
231
|
+
* @param event 鼠标事件
|
|
232
|
+
* @param excludeElList 计算鼠标点所在容器时要排除的元素列表
|
|
233
|
+
*/
|
|
234
|
+
async addContainerHighlightClassName(event, excludeElList) {
|
|
235
|
+
const doc = this.getRenderDocument();
|
|
236
|
+
if (!doc) return;
|
|
237
|
+
const els = this.getElementsFromPoint(event);
|
|
238
|
+
for (const el of els) if (!getIdFromEl()(el)?.startsWith("ghost_el_") && await this.isContainer?.(el) && !excludeElList.includes(el)) {
|
|
239
|
+
addClassName(el, doc, this.containerHighlightClassName);
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 鼠标拖拽着元素,在容器上方悬停,延迟一段时间后,对容器进行标记,如果悬停时间够长将标记成功,悬停时间短,调用方通过返回的timeoutId取消标记
|
|
245
|
+
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
|
246
|
+
* @param event 鼠标事件
|
|
247
|
+
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
248
|
+
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
249
|
+
*/
|
|
250
|
+
delayedMarkContainer(event, excludeElList = []) {
|
|
251
|
+
if (this.canAddToContainer()) return globalThis.setTimeout(() => {
|
|
252
|
+
this.addContainerHighlightClassName(event, excludeElList);
|
|
253
|
+
}, this.containerHighlightDuration);
|
|
254
|
+
}
|
|
255
|
+
getDragStatus() {
|
|
256
|
+
return this.dr?.getDragStatus();
|
|
257
|
+
}
|
|
258
|
+
updateMoveableOptions() {
|
|
259
|
+
this.dr?.updateMoveable();
|
|
260
|
+
this.multiDr?.updateMoveable();
|
|
261
|
+
}
|
|
262
|
+
destroy() {
|
|
263
|
+
this.container.removeEventListener("mousedown", this.mouseDownHandler);
|
|
264
|
+
this.container.removeEventListener("mousemove", this.mouseMoveHandler);
|
|
265
|
+
this.container.removeEventListener("mouseleave", this.mouseLeaveHandler);
|
|
266
|
+
this.container.removeEventListener("wheel", this.mouseWheelHandler);
|
|
267
|
+
this.container.removeEventListener("dblclick", this.dblclickHandler);
|
|
268
|
+
this.selectedEl = null;
|
|
269
|
+
this.selectedElList = [];
|
|
270
|
+
this.dr?.destroy();
|
|
271
|
+
this.multiDr?.destroy();
|
|
272
|
+
this.highlightLayer?.destroy();
|
|
273
|
+
this.dr = null;
|
|
274
|
+
this.multiDr = null;
|
|
275
|
+
this.highlightLayer = null;
|
|
276
|
+
}
|
|
277
|
+
on(eventName, listener) {
|
|
278
|
+
return super.on(eventName, listener);
|
|
279
|
+
}
|
|
280
|
+
emit(eventName, ...args) {
|
|
281
|
+
return super.emit(eventName, ...args);
|
|
282
|
+
}
|
|
283
|
+
createDr(config) {
|
|
284
|
+
const createDrHelper = () => new DragResizeHelper({
|
|
285
|
+
container: config.container,
|
|
286
|
+
updateDragEl: config.updateDragEl
|
|
287
|
+
});
|
|
288
|
+
const dr = new StageDragResize({
|
|
289
|
+
container: config.container,
|
|
290
|
+
disabledDragStart: config.disabledDragStart,
|
|
291
|
+
moveableOptions: config.moveableOptions && this.changeCallback(config.moveableOptions, false),
|
|
292
|
+
dragResizeHelper: createDrHelper(),
|
|
293
|
+
getRootContainer: config.getRootContainer,
|
|
294
|
+
getRenderDocument: config.getRenderDocument,
|
|
295
|
+
markContainerEnd: this.markContainerEnd.bind(this),
|
|
296
|
+
delayedMarkContainer: this.delayedMarkContainer.bind(this)
|
|
297
|
+
});
|
|
298
|
+
dr.on("update", (data) => {
|
|
299
|
+
setTimeout(() => this.emit("update", data));
|
|
300
|
+
}).on("sort", (data) => {
|
|
301
|
+
setTimeout(() => this.emit("sort", data));
|
|
302
|
+
}).on(AbleActionEventType.SELECT_PARENT, () => {
|
|
303
|
+
this.emit("select-parent");
|
|
304
|
+
}).on(AbleActionEventType.REMOVE, () => {
|
|
305
|
+
const drTarget = this.dr?.getTarget();
|
|
306
|
+
if (!drTarget) return;
|
|
307
|
+
const data = { data: [{ el: drTarget }] };
|
|
308
|
+
this.emit("remove", data);
|
|
309
|
+
}).on(AbleActionEventType.RERENDER, () => {
|
|
310
|
+
this.emit("rerender");
|
|
311
|
+
}).on("drag-start", (e) => {
|
|
312
|
+
this.emit("drag-start", e);
|
|
313
|
+
});
|
|
314
|
+
return dr;
|
|
315
|
+
}
|
|
316
|
+
createMultiDr(config) {
|
|
317
|
+
const createDrHelper = () => new DragResizeHelper({
|
|
318
|
+
container: config.container,
|
|
319
|
+
updateDragEl: config.updateDragEl
|
|
320
|
+
});
|
|
321
|
+
const multiDr = new StageMultiDragResize({
|
|
322
|
+
container: config.container,
|
|
323
|
+
moveableOptions: config.moveableOptions && this.changeCallback(config.moveableOptions, true),
|
|
324
|
+
dragResizeHelper: createDrHelper(),
|
|
325
|
+
getRootContainer: config.getRootContainer,
|
|
326
|
+
getRenderDocument: config.getRenderDocument,
|
|
327
|
+
markContainerEnd: this.markContainerEnd.bind(this),
|
|
328
|
+
delayedMarkContainer: this.delayedMarkContainer.bind(this)
|
|
329
|
+
});
|
|
330
|
+
multiDr?.on("update", (data) => {
|
|
331
|
+
this.emit("multi-update", data);
|
|
332
|
+
}).on("change-to-select", (id, e) => {
|
|
333
|
+
if (this.isMultiSelectStatus) return;
|
|
334
|
+
this.emit("change-to-select", id, e);
|
|
335
|
+
});
|
|
336
|
+
return multiDr;
|
|
337
|
+
}
|
|
338
|
+
changeCallback(options, isMulti) {
|
|
339
|
+
if (typeof options === "function") return () => {
|
|
340
|
+
if (typeof options === "function") return options({
|
|
341
|
+
targetEl: this.selectedEl,
|
|
342
|
+
targetElId: getIdFromEl()(this.selectedEl),
|
|
343
|
+
targetEls: this.selectedElList,
|
|
344
|
+
targetElIds: this.selectedElList?.map((item) => getIdFromEl()(item) || ""),
|
|
345
|
+
isMulti,
|
|
346
|
+
document: this.getRenderDocument()
|
|
347
|
+
});
|
|
348
|
+
return options;
|
|
349
|
+
};
|
|
350
|
+
return options;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* 在执行多选逻辑前,先准备好多选选中元素
|
|
354
|
+
* @param el 新选中的元素
|
|
355
|
+
* @returns 多选选中的元素列表
|
|
356
|
+
*/
|
|
357
|
+
async beforeMultiSelect(event) {
|
|
358
|
+
const el = await this.getElementFromPoint(event);
|
|
359
|
+
if (!el) return;
|
|
360
|
+
if (this.selectedEl && !this.selectedEl.className.includes("magic-ui-page")) {
|
|
361
|
+
this.selectedElList.push(this.selectedEl);
|
|
362
|
+
this.setSelectedEl(null);
|
|
363
|
+
}
|
|
364
|
+
const existIndex = this.selectedElList.findIndex((selectedDom) => getIdFromEl()(selectedDom) === getIdFromEl()(el));
|
|
365
|
+
if (existIndex !== -1) {
|
|
366
|
+
if (this.selectedElList.length > 1) this.selectedElList.splice(existIndex, 1);
|
|
367
|
+
} else this.selectedElList.push(el);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* 当前状态下能否将组件加入容器,默认是鼠标悬停一段时间加入,alt模式则是按住alt+鼠标悬停一段时间加入
|
|
371
|
+
*/
|
|
372
|
+
canAddToContainer() {
|
|
373
|
+
return this.containerHighlightType === ContainerHighlightType.DEFAULT || this.containerHighlightType === ContainerHighlightType.ALT && this.isAltKeydown;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* 结束对container的标记状态
|
|
377
|
+
* @returns 标记的容器元素,没有标记的容器时返回null
|
|
378
|
+
*/
|
|
379
|
+
markContainerEnd() {
|
|
380
|
+
const doc = this.getRenderDocument();
|
|
381
|
+
if (doc && this.canAddToContainer()) return removeClassNameByClassName(doc, this.containerHighlightClassName);
|
|
382
|
+
return null;
|
|
383
|
+
}
|
|
384
|
+
initMouseEvent() {
|
|
385
|
+
this.container.addEventListener("mousedown", this.mouseDownHandler);
|
|
386
|
+
this.container.addEventListener("mousemove", this.mouseMoveHandler);
|
|
387
|
+
this.container.addEventListener("mouseleave", this.mouseLeaveHandler);
|
|
388
|
+
this.container.addEventListener("wheel", this.mouseWheelHandler);
|
|
389
|
+
this.container.addEventListener("dblclick", this.dblclickHandler);
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* 初始化键盘事件监听
|
|
393
|
+
*/
|
|
394
|
+
initKeyEvent() {
|
|
395
|
+
const { isMac } = new Env();
|
|
396
|
+
const ctrl = isMac ? "meta" : "ctrl";
|
|
397
|
+
KeyController.global.keydown(ctrl, (e) => {
|
|
398
|
+
e.inputEvent.preventDefault();
|
|
399
|
+
if (!this.disabledMultiSelect) this.isMultiSelectStatus = true;
|
|
400
|
+
});
|
|
401
|
+
KeyController.global.on("blur", () => {
|
|
402
|
+
if (!this.disabledMultiSelect) this.isMultiSelectStatus = false;
|
|
403
|
+
this.isAltKeydown = false;
|
|
404
|
+
});
|
|
405
|
+
KeyController.global.keyup(ctrl, (e) => {
|
|
406
|
+
e.inputEvent.preventDefault();
|
|
407
|
+
if (!this.disabledMultiSelect) this.isMultiSelectStatus = false;
|
|
408
|
+
});
|
|
409
|
+
KeyController.global.keydown("alt", (e) => {
|
|
410
|
+
e.inputEvent.preventDefault();
|
|
411
|
+
this.isAltKeydown = true;
|
|
412
|
+
});
|
|
413
|
+
KeyController.global.keyup("alt", (e) => {
|
|
414
|
+
e.inputEvent.preventDefault();
|
|
415
|
+
this.markContainerEnd();
|
|
416
|
+
this.isAltKeydown = false;
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* 在down事件中集中cpu处理画布中选中操作渲染,在up事件中再通知外面的编辑器更新
|
|
421
|
+
*/
|
|
422
|
+
mouseDownHandler = (event) => {
|
|
423
|
+
const handler = async () => {
|
|
424
|
+
this.clearHighlight();
|
|
425
|
+
event.stopImmediatePropagation();
|
|
426
|
+
event.stopPropagation();
|
|
427
|
+
if (this.isStopTriggerSelect(event)) return;
|
|
428
|
+
this.container.removeEventListener("mousemove", this.mouseMoveHandler);
|
|
429
|
+
if (this.isMultiSelectStatus) {
|
|
430
|
+
await this.beforeMultiSelect(event);
|
|
431
|
+
if (this.selectedElList.length > 0) this.emit("before-multi-select", this.selectedElList);
|
|
432
|
+
} else {
|
|
433
|
+
const el = await this.getElementFromPoint(event);
|
|
434
|
+
if (!el) return;
|
|
435
|
+
this.emit("before-select", el, event);
|
|
436
|
+
}
|
|
437
|
+
getDocument().addEventListener("mouseup", this.mouseUpHandler);
|
|
438
|
+
};
|
|
439
|
+
handler();
|
|
440
|
+
};
|
|
441
|
+
isStopTriggerSelect(event) {
|
|
442
|
+
if (event.button !== MouseButton.LEFT && event.button !== MouseButton.RIGHT) return true;
|
|
443
|
+
if (!event.target) return true;
|
|
444
|
+
const targetClassList = event.target.classList;
|
|
445
|
+
if (!this.isMultiSelectStatus && targetClassList.contains("moveable-area")) return true;
|
|
446
|
+
if (targetClassList.contains("moveable-control") || isMoveableButton(event.target)) return true;
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* 在up事件中负责对外通知选中事件,通知画布之外的编辑器更新
|
|
451
|
+
*/
|
|
452
|
+
mouseUpHandler = (event) => {
|
|
453
|
+
getDocument().removeEventListener("mouseup", this.mouseUpHandler);
|
|
454
|
+
this.container.addEventListener("mousemove", this.mouseMoveHandler);
|
|
455
|
+
if (this.isMultiSelectStatus) this.emit("multi-select", this.selectedElList, event);
|
|
456
|
+
else this.emit("select", this.selectedEl, event);
|
|
457
|
+
};
|
|
458
|
+
mouseLeaveHandler = (event) => {
|
|
459
|
+
setTimeout(() => this.clearHighlight(), throttleTime);
|
|
460
|
+
this.emit("mouseleave", event);
|
|
461
|
+
};
|
|
462
|
+
mouseWheelHandler = () => {
|
|
463
|
+
this.clearHighlight();
|
|
464
|
+
};
|
|
465
|
+
dblclickHandler = (event) => {
|
|
466
|
+
this.emit("dblclick", event);
|
|
467
|
+
};
|
|
468
|
+
};
|
|
469
|
+
//#endregion
|
|
470
|
+
export { ActionManager as default };
|