@tmagic/stage 1.2.13 → 1.2.14
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.js +347 -14
- package/dist/tmagic-stage.js.map +1 -1
- package/dist/tmagic-stage.umd.cjs +360 -35
- package/dist/tmagic-stage.umd.cjs.map +1 -1
- package/package.json +6 -6
- package/types/types.d.ts +13 -13
|
@@ -4,14 +4,6 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.TMagicStage = {}, global.EventEmitter, global.KeyController, global.lodashEs, global.core, global.utils, global.MoveableHelper, global.Moveable, global.Guides));
|
|
5
5
|
})(this, (function (exports, EventEmitter, KeyController, lodashEs, core, utils, MoveableHelper, Moveable, Guides) { 'use strict';
|
|
6
6
|
|
|
7
|
-
const _interopDefaultLegacy = e => e && typeof e === 'object' && 'default' in e ? e : { default: e };
|
|
8
|
-
|
|
9
|
-
const EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
|
|
10
|
-
const KeyController__default = /*#__PURE__*/_interopDefaultLegacy(KeyController);
|
|
11
|
-
const MoveableHelper__default = /*#__PURE__*/_interopDefaultLegacy(MoveableHelper);
|
|
12
|
-
const Moveable__default = /*#__PURE__*/_interopDefaultLegacy(Moveable);
|
|
13
|
-
const Guides__default = /*#__PURE__*/_interopDefaultLegacy(Guides);
|
|
14
|
-
|
|
15
7
|
const GHOST_EL_ID_PREFIX = "ghost_el_";
|
|
16
8
|
const DRAG_EL_ID_PREFIX = "drag_el_";
|
|
17
9
|
const HIGHLIGHT_EL_ID_PREFIX = "highlight_el_";
|
|
@@ -294,19 +286,28 @@
|
|
|
294
286
|
}
|
|
295
287
|
|
|
296
288
|
class DragResizeHelper {
|
|
289
|
+
/** 目标节点在蒙层上的占位节点,用于跟鼠标交互,避免鼠标事件直接作用到目标节点 */
|
|
297
290
|
targetShadow;
|
|
291
|
+
/** 要操作的原始目标节点 */
|
|
298
292
|
target;
|
|
293
|
+
/** 多选:目标节点组 */
|
|
299
294
|
targetList = [];
|
|
295
|
+
/** 响应拖拽的状态事件,修改绝对定位布局下targetShadow的dom。
|
|
296
|
+
* MoveableHelper里面的方法是成员属性,如果DragResizeHelper用继承的方式将无法通过super去调这些方法 */
|
|
300
297
|
moveableHelper;
|
|
298
|
+
/** 流式布局下,目标节点的镜像节点 */
|
|
301
299
|
ghostEl;
|
|
300
|
+
/** 用于记录节点被改变前的位置 */
|
|
302
301
|
frameSnapShot = {
|
|
303
302
|
left: 0,
|
|
304
303
|
top: 0
|
|
305
304
|
};
|
|
305
|
+
/** 多选模式下的多个节点 */
|
|
306
306
|
framesSnapShot = [];
|
|
307
|
+
/** 布局方式:流式布局、绝对定位、固定定位 */
|
|
307
308
|
mode = Mode.ABSOLUTE;
|
|
308
309
|
constructor(config) {
|
|
309
|
-
this.moveableHelper =
|
|
310
|
+
this.moveableHelper = MoveableHelper.create({
|
|
310
311
|
useBeforeRender: true,
|
|
311
312
|
useRender: false,
|
|
312
313
|
createAuto: true
|
|
@@ -337,6 +338,10 @@
|
|
|
337
338
|
setMode(mode) {
|
|
338
339
|
this.mode = mode;
|
|
339
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* 改变大小事件开始
|
|
343
|
+
* @param e 包含了拖拽节点的dom,moveableHelper会直接修改拖拽节点
|
|
344
|
+
*/
|
|
340
345
|
onResizeStart(e) {
|
|
341
346
|
this.moveableHelper.onResizeStart(e);
|
|
342
347
|
this.frameSnapShot.top = this.target.offsetTop;
|
|
@@ -425,6 +430,9 @@
|
|
|
425
430
|
this.moveableHelper.onResizeGroupStart(e);
|
|
426
431
|
this.setFramesSnapShot(events);
|
|
427
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* 多选状态下通过拖拽边框改变大小,所有选中组件会一起改变大小
|
|
435
|
+
*/
|
|
428
436
|
onResizeGroup(e) {
|
|
429
437
|
const { events } = e;
|
|
430
438
|
events.forEach((ev) => {
|
|
@@ -498,6 +506,9 @@
|
|
|
498
506
|
}
|
|
499
507
|
return { width, height, left, top };
|
|
500
508
|
}
|
|
509
|
+
/**
|
|
510
|
+
* 多选状态设置多个节点的快照
|
|
511
|
+
*/
|
|
501
512
|
setFramesSnapShot(events) {
|
|
502
513
|
if (this.framesSnapShot.length > 0)
|
|
503
514
|
return;
|
|
@@ -514,6 +525,9 @@
|
|
|
514
525
|
});
|
|
515
526
|
});
|
|
516
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* 流式布局把目标节点复制一份进行拖拽,在拖拽结束前不影响页面原布局样式
|
|
530
|
+
*/
|
|
517
531
|
generateGhostEl(el) {
|
|
518
532
|
if (this.ghostEl) {
|
|
519
533
|
this.destroyGhostEl();
|
|
@@ -627,7 +641,7 @@
|
|
|
627
641
|
"button",
|
|
628
642
|
{
|
|
629
643
|
className: "moveable-button",
|
|
630
|
-
title: "
|
|
644
|
+
title: "选中父组件",
|
|
631
645
|
onClick: () => {
|
|
632
646
|
handler(AbleActionEventType.SELECT_PARENT);
|
|
633
647
|
}
|
|
@@ -656,7 +670,7 @@
|
|
|
656
670
|
),
|
|
657
671
|
React.createElement("button", {
|
|
658
672
|
className: "moveable-button moveable-remove-button",
|
|
659
|
-
title: "
|
|
673
|
+
title: "删除",
|
|
660
674
|
onClick: () => {
|
|
661
675
|
handler(AbleActionEventType.REMOVE);
|
|
662
676
|
}
|
|
@@ -666,13 +680,20 @@
|
|
|
666
680
|
}
|
|
667
681
|
});
|
|
668
682
|
|
|
669
|
-
class MoveableOptionsManager extends
|
|
683
|
+
class MoveableOptionsManager extends EventEmitter {
|
|
684
|
+
/** 布局方式:流式布局、绝对定位、固定定位 */
|
|
670
685
|
mode = Mode.ABSOLUTE;
|
|
686
|
+
/** 画布容器 */
|
|
671
687
|
container;
|
|
688
|
+
/** 水平参考线 */
|
|
672
689
|
horizontalGuidelines = [];
|
|
690
|
+
/** 垂直参考线 */
|
|
673
691
|
verticalGuidelines = [];
|
|
692
|
+
/** 对齐元素集合 */
|
|
674
693
|
elementGuidelines = [];
|
|
694
|
+
/** 由外部调用方(编辑器)传入进来的moveable默认参数,可以为空,也可以是一个回调函数 */
|
|
675
695
|
customizedOptions;
|
|
696
|
+
/** 获取整个画布的根元素(在StageCore的mount函数中挂载的container) */
|
|
676
697
|
getRootContainer;
|
|
677
698
|
constructor(config) {
|
|
678
699
|
super();
|
|
@@ -680,6 +701,11 @@
|
|
|
680
701
|
this.container = config.container;
|
|
681
702
|
this.getRootContainer = config.getRootContainer;
|
|
682
703
|
}
|
|
704
|
+
/**
|
|
705
|
+
* 设置水平/垂直参考线
|
|
706
|
+
* @param type 参考线类型
|
|
707
|
+
* @param guidelines 参考线坐标数组
|
|
708
|
+
*/
|
|
683
709
|
setGuidelines(type, guidelines) {
|
|
684
710
|
if (type === GuidesType.HORIZONTAL) {
|
|
685
711
|
this.horizontalGuidelines = guidelines;
|
|
@@ -688,11 +714,19 @@
|
|
|
688
714
|
}
|
|
689
715
|
this.emit("update-moveable");
|
|
690
716
|
}
|
|
717
|
+
/**
|
|
718
|
+
* 清除横向和纵向的参考线
|
|
719
|
+
*/
|
|
691
720
|
clearGuides() {
|
|
692
721
|
this.horizontalGuidelines = [];
|
|
693
722
|
this.verticalGuidelines = [];
|
|
694
723
|
this.emit("update-moveable");
|
|
695
724
|
}
|
|
725
|
+
/**
|
|
726
|
+
* 设置有哪些元素要辅助对齐
|
|
727
|
+
* @param selectedElList 选中的元素列表,需要排除在对齐元素之外
|
|
728
|
+
* @param allElList 全部元素列表
|
|
729
|
+
*/
|
|
696
730
|
setElementGuidelines(selectedElList, allElList) {
|
|
697
731
|
this.elementGuidelines.forEach((node) => {
|
|
698
732
|
node.remove();
|
|
@@ -702,11 +736,21 @@
|
|
|
702
736
|
this.container.append(this.createGuidelineElements(selectedElList, allElList));
|
|
703
737
|
}
|
|
704
738
|
}
|
|
739
|
+
/**
|
|
740
|
+
* 获取moveable参数
|
|
741
|
+
* @param isMultiSelect 是否多选模式
|
|
742
|
+
* @param runtimeOptions 调用时实时传进来的的moveable参数
|
|
743
|
+
* @returns moveable所需参数
|
|
744
|
+
*/
|
|
705
745
|
getOptions(isMultiSelect, runtimeOptions = {}) {
|
|
706
746
|
const defaultOptions = this.getDefaultOptions(isMultiSelect);
|
|
707
747
|
const customizedOptions = this.getCustomizeOptions();
|
|
708
748
|
return lodashEs.merge(defaultOptions, customizedOptions, runtimeOptions);
|
|
709
749
|
}
|
|
750
|
+
/**
|
|
751
|
+
* 获取单选和多选的moveable公共参数
|
|
752
|
+
* @returns moveable公共参数
|
|
753
|
+
*/
|
|
710
754
|
getDefaultOptions(isMultiSelect) {
|
|
711
755
|
const isSortable = this.mode === Mode.SORTABLE;
|
|
712
756
|
const commonOptions = {
|
|
@@ -721,6 +765,7 @@
|
|
|
721
765
|
elementGuidelines: this.elementGuidelines,
|
|
722
766
|
bounds: {
|
|
723
767
|
top: 0,
|
|
768
|
+
// 设置0的话无法移动到left为0,所以只能设置为-1
|
|
724
769
|
left: -1,
|
|
725
770
|
right: this.container.clientWidth - 1,
|
|
726
771
|
bottom: isSortable ? void 0 : this.container.clientHeight
|
|
@@ -729,6 +774,10 @@
|
|
|
729
774
|
const differenceOptions = isMultiSelect ? this.getMultiOptions() : this.getSingleOptions();
|
|
730
775
|
return lodashEs.merge(commonOptions, differenceOptions);
|
|
731
776
|
}
|
|
777
|
+
/**
|
|
778
|
+
* 获取单选下的差异化参数
|
|
779
|
+
* @returns {MoveableOptions} moveable options参数
|
|
780
|
+
*/
|
|
732
781
|
getSingleOptions() {
|
|
733
782
|
const isAbsolute = this.mode === Mode.ABSOLUTE;
|
|
734
783
|
const isFixed = this.mode === Mode.FIXED;
|
|
@@ -762,6 +811,10 @@
|
|
|
762
811
|
ables: [MoveableActionsAble(this.actionHandler.bind(this))]
|
|
763
812
|
};
|
|
764
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* 获取多选下的差异化参数
|
|
816
|
+
* @returns {MoveableOptions} moveable options参数
|
|
817
|
+
*/
|
|
765
818
|
getMultiOptions() {
|
|
766
819
|
return {
|
|
767
820
|
defaultGroupRotate: 0,
|
|
@@ -772,15 +825,27 @@
|
|
|
772
825
|
padding: { left: 0, top: 0, right: 0, bottom: 0 }
|
|
773
826
|
};
|
|
774
827
|
}
|
|
828
|
+
/**
|
|
829
|
+
* 获取业务方自定义的moveable参数
|
|
830
|
+
*/
|
|
775
831
|
getCustomizeOptions() {
|
|
776
832
|
if (typeof this.customizedOptions === "function") {
|
|
777
833
|
return this.customizedOptions();
|
|
778
834
|
}
|
|
779
835
|
return this.customizedOptions;
|
|
780
836
|
}
|
|
837
|
+
/**
|
|
838
|
+
* 这是给selectParentAbles的回调函数,用于触发选中父元素事件
|
|
839
|
+
*/
|
|
781
840
|
actionHandler(type) {
|
|
782
841
|
this.emit(type);
|
|
783
842
|
}
|
|
843
|
+
/**
|
|
844
|
+
* 为需要辅助对齐的元素创建div
|
|
845
|
+
* @param selectedElList 选中的元素列表,需要排除在对齐元素之外
|
|
846
|
+
* @param allElList 全部元素列表
|
|
847
|
+
* @returns frame 辅助对齐元素集合的页面片
|
|
848
|
+
*/
|
|
784
849
|
createGuidelineElements(selectedElList, allElList) {
|
|
785
850
|
const frame = globalThis.document.createDocumentFragment();
|
|
786
851
|
for (const node of allElList) {
|
|
@@ -795,6 +860,12 @@
|
|
|
795
860
|
}
|
|
796
861
|
return frame;
|
|
797
862
|
}
|
|
863
|
+
/**
|
|
864
|
+
* 判断一个元素是否在元素列表里面
|
|
865
|
+
* @param ele 元素
|
|
866
|
+
* @param eleList 元素列表
|
|
867
|
+
* @returns 是否在元素列表里面
|
|
868
|
+
*/
|
|
798
869
|
isInElementList(ele, eleList) {
|
|
799
870
|
for (const eleItem of eleList) {
|
|
800
871
|
if (ele === eleItem)
|
|
@@ -805,8 +876,11 @@
|
|
|
805
876
|
}
|
|
806
877
|
|
|
807
878
|
class StageDragResize extends MoveableOptionsManager {
|
|
879
|
+
/** 目标节点 */
|
|
808
880
|
target;
|
|
881
|
+
/** Moveable拖拽类实例 */
|
|
809
882
|
moveable;
|
|
883
|
+
/** 拖动状态 */
|
|
810
884
|
dragStatus = StageDragStatus.END;
|
|
811
885
|
dragResizeHelper;
|
|
812
886
|
disabledDragStart;
|
|
@@ -829,6 +903,12 @@
|
|
|
829
903
|
getTarget() {
|
|
830
904
|
return this.target;
|
|
831
905
|
}
|
|
906
|
+
/**
|
|
907
|
+
* 将选中框渲染并覆盖到选中的组件Dom节点上方
|
|
908
|
+
* 当选中的节点不是absolute时,会创建一个新的节点出来作为拖拽目标
|
|
909
|
+
* @param el 选中组件的Dom节点元素
|
|
910
|
+
* @param event 鼠标事件
|
|
911
|
+
*/
|
|
832
912
|
select(el, event) {
|
|
833
913
|
if (!this.moveable || el !== this.target) {
|
|
834
914
|
this.initMoveable(el);
|
|
@@ -839,11 +919,14 @@
|
|
|
839
919
|
this.moveable?.dragStart(event);
|
|
840
920
|
}
|
|
841
921
|
}
|
|
922
|
+
/**
|
|
923
|
+
* 初始化选中框并渲染出来
|
|
924
|
+
*/
|
|
842
925
|
updateMoveable(el = this.target) {
|
|
843
926
|
if (!this.moveable)
|
|
844
927
|
return;
|
|
845
928
|
if (!el)
|
|
846
|
-
throw new Error("
|
|
929
|
+
throw new Error("未选中任何节点");
|
|
847
930
|
const options = this.init(el);
|
|
848
931
|
Object.entries(options).forEach(([key, value]) => {
|
|
849
932
|
this.moveable[key] = value;
|
|
@@ -857,6 +940,9 @@
|
|
|
857
940
|
this.moveable.target = null;
|
|
858
941
|
this.moveable.updateTarget();
|
|
859
942
|
}
|
|
943
|
+
/**
|
|
944
|
+
* 销毁实例
|
|
945
|
+
*/
|
|
860
946
|
destroy() {
|
|
861
947
|
this.moveable?.destroy();
|
|
862
948
|
this.dragResizeHelper.destroy();
|
|
@@ -881,7 +967,7 @@
|
|
|
881
967
|
const options = this.init(el);
|
|
882
968
|
this.dragResizeHelper.clear();
|
|
883
969
|
this.moveable?.destroy();
|
|
884
|
-
this.moveable = new
|
|
970
|
+
this.moveable = new Moveable(this.container, {
|
|
885
971
|
...options
|
|
886
972
|
});
|
|
887
973
|
this.bindResizeEvent();
|
|
@@ -891,7 +977,7 @@
|
|
|
891
977
|
}
|
|
892
978
|
bindResizeEvent() {
|
|
893
979
|
if (!this.moveable)
|
|
894
|
-
throw new Error("moveable
|
|
980
|
+
throw new Error("moveable 未初始化");
|
|
895
981
|
this.moveable.on("resizeStart", (e) => {
|
|
896
982
|
if (!this.target)
|
|
897
983
|
return;
|
|
@@ -909,11 +995,11 @@
|
|
|
909
995
|
}
|
|
910
996
|
bindDragEvent() {
|
|
911
997
|
if (!this.moveable)
|
|
912
|
-
throw new Error("moveable
|
|
998
|
+
throw new Error("moveable 未初始化");
|
|
913
999
|
let timeout;
|
|
914
1000
|
this.moveable.on("dragStart", (e) => {
|
|
915
1001
|
if (!this.target)
|
|
916
|
-
throw new Error("
|
|
1002
|
+
throw new Error("未选中组件");
|
|
917
1003
|
this.dragStatus = StageDragStatus.START;
|
|
918
1004
|
this.dragResizeHelper.onDragStart(e);
|
|
919
1005
|
}).on("drag", (e) => {
|
|
@@ -951,7 +1037,7 @@
|
|
|
951
1037
|
}
|
|
952
1038
|
bindRotateEvent() {
|
|
953
1039
|
if (!this.moveable)
|
|
954
|
-
throw new Error("moveable
|
|
1040
|
+
throw new Error("moveable 未初始化");
|
|
955
1041
|
this.moveable.on("rotateStart", (e) => {
|
|
956
1042
|
this.dragStatus = StageDragStatus.START;
|
|
957
1043
|
this.dragResizeHelper.onRotateStart(e);
|
|
@@ -977,7 +1063,7 @@
|
|
|
977
1063
|
}
|
|
978
1064
|
bindScaleEvent() {
|
|
979
1065
|
if (!this.moveable)
|
|
980
|
-
throw new Error("moveable
|
|
1066
|
+
throw new Error("moveable 未初始化");
|
|
981
1067
|
this.moveable.on("scaleStart", (e) => {
|
|
982
1068
|
this.dragStatus = StageDragStatus.START;
|
|
983
1069
|
this.dragResizeHelper.onScaleStart(e);
|
|
@@ -1003,7 +1089,7 @@
|
|
|
1003
1089
|
}
|
|
1004
1090
|
sort() {
|
|
1005
1091
|
if (!this.target || !this.dragResizeHelper.getGhostEl())
|
|
1006
|
-
throw new Error("
|
|
1092
|
+
throw new Error("未知错误");
|
|
1007
1093
|
const { top } = this.dragResizeHelper.getGhostEl().getBoundingClientRect();
|
|
1008
1094
|
const { top: oriTop } = this.target.getBoundingClientRect();
|
|
1009
1095
|
const deltaTop = top - oriTop;
|
|
@@ -1056,18 +1142,25 @@
|
|
|
1056
1142
|
idPrefix: HIGHLIGHT_EL_ID_PREFIX
|
|
1057
1143
|
});
|
|
1058
1144
|
}
|
|
1145
|
+
/**
|
|
1146
|
+
* 高亮鼠标悬停的组件
|
|
1147
|
+
* @param el 选中组件的Dom节点元素
|
|
1148
|
+
*/
|
|
1059
1149
|
highlight(el) {
|
|
1060
1150
|
if (!el || el === this.target)
|
|
1061
1151
|
return;
|
|
1062
1152
|
this.target = el;
|
|
1063
1153
|
this.moveable?.destroy();
|
|
1064
|
-
this.moveable = new
|
|
1154
|
+
this.moveable = new Moveable(this.container, {
|
|
1065
1155
|
target: this.targetShadow.update(el),
|
|
1066
1156
|
origin: false,
|
|
1067
1157
|
rootContainer: this.getRootContainer(),
|
|
1068
1158
|
zoom: 2
|
|
1069
1159
|
});
|
|
1070
1160
|
}
|
|
1161
|
+
/**
|
|
1162
|
+
* 清空高亮
|
|
1163
|
+
*/
|
|
1071
1164
|
clearHighlight() {
|
|
1072
1165
|
if (!this.moveable || !this.target)
|
|
1073
1166
|
return;
|
|
@@ -1075,6 +1168,9 @@
|
|
|
1075
1168
|
this.moveable.target = null;
|
|
1076
1169
|
this.moveable.updateTarget();
|
|
1077
1170
|
}
|
|
1171
|
+
/**
|
|
1172
|
+
* 销毁实例
|
|
1173
|
+
*/
|
|
1078
1174
|
destroy() {
|
|
1079
1175
|
this.moveable?.destroy();
|
|
1080
1176
|
this.targetShadow.destroy();
|
|
@@ -1082,8 +1178,11 @@
|
|
|
1082
1178
|
}
|
|
1083
1179
|
|
|
1084
1180
|
class StageMultiDragResize extends MoveableOptionsManager {
|
|
1181
|
+
/** 画布容器 */
|
|
1085
1182
|
container;
|
|
1183
|
+
/** 多选:目标节点组 */
|
|
1086
1184
|
targetList = [];
|
|
1185
|
+
/** Moveable多选拖拽类实例 */
|
|
1087
1186
|
moveableForMulti;
|
|
1088
1187
|
dragStatus = StageDragStatus.END;
|
|
1089
1188
|
dragResizeHelper;
|
|
@@ -1108,6 +1207,10 @@
|
|
|
1108
1207
|
}
|
|
1109
1208
|
});
|
|
1110
1209
|
}
|
|
1210
|
+
/**
|
|
1211
|
+
* 多选
|
|
1212
|
+
* @param els
|
|
1213
|
+
*/
|
|
1111
1214
|
multiSelect(els) {
|
|
1112
1215
|
if (els.length === 0) {
|
|
1113
1216
|
return;
|
|
@@ -1119,7 +1222,7 @@
|
|
|
1119
1222
|
this.setElementGuidelines(this.targetList, elementGuidelines);
|
|
1120
1223
|
this.moveableForMulti?.destroy();
|
|
1121
1224
|
this.dragResizeHelper.clear();
|
|
1122
|
-
this.moveableForMulti = new
|
|
1225
|
+
this.moveableForMulti = new Moveable(
|
|
1123
1226
|
this.container,
|
|
1124
1227
|
this.getOptions(true, {
|
|
1125
1228
|
target: this.dragResizeHelper.getShadowEls()
|
|
@@ -1177,7 +1280,7 @@
|
|
|
1177
1280
|
if (!this.moveableForMulti)
|
|
1178
1281
|
return;
|
|
1179
1282
|
if (!eleList)
|
|
1180
|
-
throw new Error("
|
|
1283
|
+
throw new Error("未选中任何节点");
|
|
1181
1284
|
this.targetList = eleList;
|
|
1182
1285
|
this.dragResizeHelper.setTargetList(eleList);
|
|
1183
1286
|
const options = this.getOptions(true, {
|
|
@@ -1188,6 +1291,9 @@
|
|
|
1188
1291
|
});
|
|
1189
1292
|
this.moveableForMulti.updateTarget();
|
|
1190
1293
|
}
|
|
1294
|
+
/**
|
|
1295
|
+
* 清除多选状态
|
|
1296
|
+
*/
|
|
1191
1297
|
clearSelectStatus() {
|
|
1192
1298
|
if (!this.moveableForMulti)
|
|
1193
1299
|
return;
|
|
@@ -1196,10 +1302,17 @@
|
|
|
1196
1302
|
this.moveableForMulti.updateTarget();
|
|
1197
1303
|
this.targetList = [];
|
|
1198
1304
|
}
|
|
1305
|
+
/**
|
|
1306
|
+
* 销毁实例
|
|
1307
|
+
*/
|
|
1199
1308
|
destroy() {
|
|
1200
1309
|
this.moveableForMulti?.destroy();
|
|
1201
1310
|
this.dragResizeHelper.destroy();
|
|
1202
1311
|
}
|
|
1312
|
+
/**
|
|
1313
|
+
* 拖拽完成后将更新的位置信息暴露给上层业务方,业务方可以接收事件进行保存
|
|
1314
|
+
* @param isResize 是否进行大小缩放
|
|
1315
|
+
*/
|
|
1203
1316
|
update(isResize = false, parentEl = null) {
|
|
1204
1317
|
if (this.targetList.length === 0)
|
|
1205
1318
|
return;
|
|
@@ -1219,17 +1332,25 @@
|
|
|
1219
1332
|
|
|
1220
1333
|
const throttleTime = 100;
|
|
1221
1334
|
const defaultContainerHighlightDuration = 800;
|
|
1222
|
-
class ActionManager extends
|
|
1335
|
+
class ActionManager extends EventEmitter {
|
|
1223
1336
|
dr;
|
|
1224
1337
|
multiDr;
|
|
1225
1338
|
highlightLayer;
|
|
1339
|
+
/** 单选、多选、高亮的容器(蒙层的content) */
|
|
1226
1340
|
container;
|
|
1341
|
+
/** 当前选中的节点 */
|
|
1227
1342
|
selectedEl;
|
|
1343
|
+
/** 多选选中的节点组 */
|
|
1228
1344
|
selectedElList = [];
|
|
1345
|
+
/** 当前高亮的节点 */
|
|
1229
1346
|
highlightedEl;
|
|
1347
|
+
/** 当前是否处于多选状态 */
|
|
1230
1348
|
isMultiSelectStatus = false;
|
|
1349
|
+
/** 当拖拽组件到容器上方进入可加入容器状态时,给容器添加的一个class名称 */
|
|
1231
1350
|
containerHighlightClassName;
|
|
1351
|
+
/** 当拖拽组件到容器上方时,需要悬停多久才能将组件加入容器 */
|
|
1232
1352
|
containerHighlightDuration;
|
|
1353
|
+
/** 将组件加入容器的操作方式 */
|
|
1233
1354
|
containerHighlightType;
|
|
1234
1355
|
isAltKeydown = false;
|
|
1235
1356
|
getTargetElement;
|
|
@@ -1288,18 +1409,33 @@
|
|
|
1288
1409
|
this.initKeyEvent();
|
|
1289
1410
|
this.initActionEvent();
|
|
1290
1411
|
}
|
|
1412
|
+
/**
|
|
1413
|
+
* 设置水平/垂直参考线
|
|
1414
|
+
* @param type 参考线类型
|
|
1415
|
+
* @param guidelines 参考线坐标数组
|
|
1416
|
+
*/
|
|
1291
1417
|
setGuidelines(type, guidelines) {
|
|
1292
1418
|
this.dr.setGuidelines(type, guidelines);
|
|
1293
1419
|
this.multiDr.setGuidelines(type, guidelines);
|
|
1294
1420
|
}
|
|
1421
|
+
/**
|
|
1422
|
+
* 清空所有参考线
|
|
1423
|
+
*/
|
|
1295
1424
|
clearGuides() {
|
|
1296
1425
|
this.dr.clearGuides();
|
|
1297
1426
|
this.multiDr.clearGuides();
|
|
1298
1427
|
}
|
|
1428
|
+
/**
|
|
1429
|
+
* 更新moveable,外部主要调用场景是元素配置变更、页面大小变更
|
|
1430
|
+
* @param el 变更的元素
|
|
1431
|
+
*/
|
|
1299
1432
|
updateMoveable(el) {
|
|
1300
1433
|
this.dr.updateMoveable(el);
|
|
1301
1434
|
this.multiDr.updateMoveable();
|
|
1302
1435
|
}
|
|
1436
|
+
/**
|
|
1437
|
+
* 判断是否单选选中的元素
|
|
1438
|
+
*/
|
|
1303
1439
|
isSelectedEl(el) {
|
|
1304
1440
|
return el.id === this.selectedEl?.id;
|
|
1305
1441
|
}
|
|
@@ -1312,6 +1448,11 @@
|
|
|
1312
1448
|
getSelectedElList() {
|
|
1313
1449
|
return this.selectedElList;
|
|
1314
1450
|
}
|
|
1451
|
+
/**
|
|
1452
|
+
* 获取鼠标下方第一个可选中元素,如果元素层叠,返回到是最上层元素
|
|
1453
|
+
* @param event 鼠标事件
|
|
1454
|
+
* @returns 鼠标下方第一个可选中元素
|
|
1455
|
+
*/
|
|
1315
1456
|
async getElementFromPoint(event) {
|
|
1316
1457
|
const els = this.getElementsFromPoint(event);
|
|
1317
1458
|
let stopped = false;
|
|
@@ -1324,6 +1465,13 @@
|
|
|
1324
1465
|
}
|
|
1325
1466
|
}
|
|
1326
1467
|
}
|
|
1468
|
+
/**
|
|
1469
|
+
* 判断一个元素能否在当前场景被选中
|
|
1470
|
+
* @param el 被判断的元素
|
|
1471
|
+
* @param event 鼠标事件
|
|
1472
|
+
* @param stop 通过该元素如果得知剩下的元素都不可被选中,通知调用方终止对剩下元素的判断
|
|
1473
|
+
* @returns 能否选中
|
|
1474
|
+
*/
|
|
1327
1475
|
async isElCanSelect(el, event, stop) {
|
|
1328
1476
|
const canSelectByProp = await this.canSelect(el, event, stop);
|
|
1329
1477
|
if (!canSelectByProp)
|
|
@@ -1333,6 +1481,9 @@
|
|
|
1333
1481
|
}
|
|
1334
1482
|
return true;
|
|
1335
1483
|
}
|
|
1484
|
+
/**
|
|
1485
|
+
* 判断一个元素是否可以被多选,如果当前元素是page,则调stop函数告诉调用方不必继续判断其它元素了
|
|
1486
|
+
*/
|
|
1336
1487
|
canMultiSelect(el, stop) {
|
|
1337
1488
|
if (el.className.includes(PAGE_CLASS)) {
|
|
1338
1489
|
stop();
|
|
@@ -1382,6 +1533,10 @@
|
|
|
1382
1533
|
this.setHighlightEl(void 0);
|
|
1383
1534
|
this.highlightLayer.clearHighlight();
|
|
1384
1535
|
}
|
|
1536
|
+
/**
|
|
1537
|
+
* 用于在切换选择模式时清除上一次的状态
|
|
1538
|
+
* @param selectType 需要清理的选择模式
|
|
1539
|
+
*/
|
|
1385
1540
|
clearSelectStatus(selectType) {
|
|
1386
1541
|
if (selectType === SelectStatus.MULTI_SELECT) {
|
|
1387
1542
|
this.multiDr.clearSelectStatus();
|
|
@@ -1390,6 +1545,11 @@
|
|
|
1390
1545
|
this.dr.clearSelectStatus();
|
|
1391
1546
|
}
|
|
1392
1547
|
}
|
|
1548
|
+
/**
|
|
1549
|
+
* 找到鼠标下方的容器,通过添加className对容器进行标记
|
|
1550
|
+
* @param event 鼠标事件
|
|
1551
|
+
* @param excludeElList 计算鼠标点所在容器时要排除的元素列表
|
|
1552
|
+
*/
|
|
1393
1553
|
async addContainerHighlightClassName(event, excludeElList) {
|
|
1394
1554
|
const doc = this.getRenderDocument();
|
|
1395
1555
|
if (!doc)
|
|
@@ -1402,6 +1562,13 @@
|
|
|
1402
1562
|
}
|
|
1403
1563
|
}
|
|
1404
1564
|
}
|
|
1565
|
+
/**
|
|
1566
|
+
* 鼠标拖拽着元素,在容器上方悬停,延迟一段时间后,对容器进行标记,如果悬停时间够长将标记成功,悬停时间短,调用方通过返回的timeoutId取消标记
|
|
1567
|
+
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
|
1568
|
+
* @param event 鼠标事件
|
|
1569
|
+
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
1570
|
+
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
1571
|
+
*/
|
|
1405
1572
|
delayedMarkContainer(event, excludeElList = []) {
|
|
1406
1573
|
if (this.canAddToContainer()) {
|
|
1407
1574
|
return globalThis.setTimeout(() => {
|
|
@@ -1433,6 +1600,11 @@
|
|
|
1433
1600
|
}
|
|
1434
1601
|
return options;
|
|
1435
1602
|
}
|
|
1603
|
+
/**
|
|
1604
|
+
* 在执行多选逻辑前,先准备好多选选中元素
|
|
1605
|
+
* @param el 新选中的元素
|
|
1606
|
+
* @returns 多选选中的元素列表
|
|
1607
|
+
*/
|
|
1436
1608
|
async beforeMultiSelect(event) {
|
|
1437
1609
|
const el = await this.getElementFromPoint(event);
|
|
1438
1610
|
if (!el)
|
|
@@ -1448,9 +1620,16 @@
|
|
|
1448
1620
|
this.selectedElList.push(el);
|
|
1449
1621
|
}
|
|
1450
1622
|
}
|
|
1623
|
+
/**
|
|
1624
|
+
* 当前状态下能否将组件加入容器,默认是鼠标悬停一段时间加入,alt模式则是按住alt+鼠标悬停一段时间加入
|
|
1625
|
+
*/
|
|
1451
1626
|
canAddToContainer() {
|
|
1452
1627
|
return this.containerHighlightType === ContainerHighlightType.DEFAULT || this.containerHighlightType === ContainerHighlightType.ALT && this.isAltKeydown;
|
|
1453
1628
|
}
|
|
1629
|
+
/**
|
|
1630
|
+
* 结束对container的标记状态
|
|
1631
|
+
* @returns 标记的容器元素,没有标记的容器时返回null
|
|
1632
|
+
*/
|
|
1454
1633
|
markContainerEnd() {
|
|
1455
1634
|
const doc = this.getRenderDocument();
|
|
1456
1635
|
if (doc && this.canAddToContainer()) {
|
|
@@ -1464,30 +1643,36 @@
|
|
|
1464
1643
|
this.container.addEventListener("mouseleave", this.mouseLeaveHandler);
|
|
1465
1644
|
this.container.addEventListener("wheel", this.mouseWheelHandler);
|
|
1466
1645
|
}
|
|
1646
|
+
/**
|
|
1647
|
+
* 初始化键盘事件监听
|
|
1648
|
+
*/
|
|
1467
1649
|
initKeyEvent() {
|
|
1468
1650
|
const { isMac } = new core.Env();
|
|
1469
1651
|
const ctrl = isMac ? "meta" : "ctrl";
|
|
1470
|
-
|
|
1652
|
+
KeyController.global.keydown(ctrl, (e) => {
|
|
1471
1653
|
e.inputEvent.preventDefault();
|
|
1472
1654
|
this.isMultiSelectStatus = true;
|
|
1473
1655
|
});
|
|
1474
|
-
|
|
1656
|
+
KeyController.global.on("blur", () => {
|
|
1475
1657
|
this.isMultiSelectStatus = false;
|
|
1476
1658
|
});
|
|
1477
|
-
|
|
1659
|
+
KeyController.global.keyup(ctrl, (e) => {
|
|
1478
1660
|
e.inputEvent.preventDefault();
|
|
1479
1661
|
this.isMultiSelectStatus = false;
|
|
1480
1662
|
});
|
|
1481
|
-
|
|
1663
|
+
KeyController.global.keydown("alt", (e) => {
|
|
1482
1664
|
e.inputEvent.preventDefault();
|
|
1483
1665
|
this.isAltKeydown = true;
|
|
1484
1666
|
});
|
|
1485
|
-
|
|
1667
|
+
KeyController.global.keyup("alt", (e) => {
|
|
1486
1668
|
e.inputEvent.preventDefault();
|
|
1487
1669
|
this.markContainerEnd();
|
|
1488
1670
|
this.isAltKeydown = false;
|
|
1489
1671
|
});
|
|
1490
1672
|
}
|
|
1673
|
+
/**
|
|
1674
|
+
* 处理单选、多选抛出来的事件
|
|
1675
|
+
*/
|
|
1491
1676
|
initActionEvent() {
|
|
1492
1677
|
this.dr.on("update", (data) => {
|
|
1493
1678
|
setTimeout(() => this.emit("update", data));
|
|
@@ -1513,6 +1698,9 @@
|
|
|
1513
1698
|
this.emit("change-to-select", el);
|
|
1514
1699
|
});
|
|
1515
1700
|
}
|
|
1701
|
+
/**
|
|
1702
|
+
* 在down事件中集中cpu处理画布中选中操作渲染,在up事件中再通知外面的编辑器更新
|
|
1703
|
+
*/
|
|
1516
1704
|
mouseDownHandler = async (event) => {
|
|
1517
1705
|
this.clearHighlight();
|
|
1518
1706
|
event.stopImmediatePropagation();
|
|
@@ -1547,6 +1735,9 @@
|
|
|
1547
1735
|
}
|
|
1548
1736
|
return false;
|
|
1549
1737
|
}
|
|
1738
|
+
/**
|
|
1739
|
+
* 在up事件中负责对外通知选中事件,通知画布之外的编辑器更新
|
|
1740
|
+
*/
|
|
1550
1741
|
mouseUpHandler = () => {
|
|
1551
1742
|
utils.getDocument().removeEventListener("mouseup", this.mouseUpHandler);
|
|
1552
1743
|
this.container.addEventListener("mousemove", this.mouseMoveHandler);
|
|
@@ -1564,7 +1755,7 @@
|
|
|
1564
1755
|
};
|
|
1565
1756
|
}
|
|
1566
1757
|
|
|
1567
|
-
class Rule extends
|
|
1758
|
+
class Rule extends EventEmitter {
|
|
1568
1759
|
hGuides;
|
|
1569
1760
|
vGuides;
|
|
1570
1761
|
horizontalGuidelines = [];
|
|
@@ -1585,6 +1776,10 @@
|
|
|
1585
1776
|
});
|
|
1586
1777
|
this.containerResizeObserver.observe(this.container);
|
|
1587
1778
|
}
|
|
1779
|
+
/**
|
|
1780
|
+
* 是否显示辅助线
|
|
1781
|
+
* @param isShowGuides 是否显示
|
|
1782
|
+
*/
|
|
1588
1783
|
showGuides(isShowGuides = true) {
|
|
1589
1784
|
this.isShowGuides = isShowGuides;
|
|
1590
1785
|
this.hGuides.setState({
|
|
@@ -1612,9 +1807,16 @@
|
|
|
1612
1807
|
guides: vLines
|
|
1613
1808
|
});
|
|
1614
1809
|
}
|
|
1810
|
+
/**
|
|
1811
|
+
* 清空所有参考线
|
|
1812
|
+
*/
|
|
1615
1813
|
clearGuides() {
|
|
1616
1814
|
this.setGuides([[], []]);
|
|
1617
1815
|
}
|
|
1816
|
+
/**
|
|
1817
|
+
* 是否显示标尺
|
|
1818
|
+
* @param show 是否显示
|
|
1819
|
+
*/
|
|
1618
1820
|
showRule(show = true) {
|
|
1619
1821
|
if (show) {
|
|
1620
1822
|
this.hGuides.destroy();
|
|
@@ -1654,7 +1856,7 @@
|
|
|
1654
1856
|
width: type === GuidesType.HORIZONTAL ? "100%" : "30px",
|
|
1655
1857
|
height: type === GuidesType.HORIZONTAL ? "30px" : "100%"
|
|
1656
1858
|
});
|
|
1657
|
-
createGuides = (type, defaultGuides = []) => new
|
|
1859
|
+
createGuides = (type, defaultGuides = []) => new Guides(this.container, {
|
|
1658
1860
|
type,
|
|
1659
1861
|
defaultGuides,
|
|
1660
1862
|
displayDragPos: true,
|
|
@@ -1744,6 +1946,11 @@
|
|
|
1744
1946
|
this.content.style.height = `${this.height}px`;
|
|
1745
1947
|
}
|
|
1746
1948
|
}
|
|
1949
|
+
/**
|
|
1950
|
+
* 初始化视窗和蒙层监听,监听元素是否在视窗区域、监听mask蒙层所在的wrapper大小变化
|
|
1951
|
+
* @description 初始化视窗和蒙层监听
|
|
1952
|
+
* @param page 页面Dom节点
|
|
1953
|
+
*/
|
|
1747
1954
|
observe(page) {
|
|
1748
1955
|
if (!page)
|
|
1749
1956
|
return;
|
|
@@ -1751,6 +1958,10 @@
|
|
|
1751
1958
|
this.initObserverIntersection();
|
|
1752
1959
|
this.initObserverWrapper();
|
|
1753
1960
|
}
|
|
1961
|
+
/**
|
|
1962
|
+
* 处理页面大小变更,同步页面和mask大小
|
|
1963
|
+
* @param entries ResizeObserverEntry,获取页面最新大小
|
|
1964
|
+
*/
|
|
1754
1965
|
pageResize(entries) {
|
|
1755
1966
|
const [entry] = entries;
|
|
1756
1967
|
const { clientHeight, clientWidth } = entry.target;
|
|
@@ -1758,12 +1969,20 @@
|
|
|
1758
1969
|
this.setWidth(clientWidth);
|
|
1759
1970
|
this.scroll();
|
|
1760
1971
|
}
|
|
1972
|
+
/**
|
|
1973
|
+
* 监听一个组件是否在画布可视区域内
|
|
1974
|
+
* @param el 被选中的组件,可能是左侧目录树中选中的
|
|
1975
|
+
*/
|
|
1761
1976
|
observerIntersection(el) {
|
|
1762
1977
|
this.intersectionObserver?.observe(el);
|
|
1763
1978
|
}
|
|
1979
|
+
/**
|
|
1980
|
+
* 挂载Dom节点
|
|
1981
|
+
* @param el 将蒙层挂载到该Dom节点上
|
|
1982
|
+
*/
|
|
1764
1983
|
mount(el) {
|
|
1765
1984
|
if (!this.content)
|
|
1766
|
-
throw new Error("content
|
|
1985
|
+
throw new Error("content 不存在");
|
|
1767
1986
|
el.appendChild(this.wrapper);
|
|
1768
1987
|
}
|
|
1769
1988
|
setLayout(el) {
|
|
@@ -1777,6 +1996,9 @@
|
|
|
1777
1996
|
this.scrollTop = this.pageScrollParent.scrollTop;
|
|
1778
1997
|
this.scroll();
|
|
1779
1998
|
}
|
|
1999
|
+
/**
|
|
2000
|
+
* 销毁实例
|
|
2001
|
+
*/
|
|
1780
2002
|
destroy() {
|
|
1781
2003
|
this.content?.remove();
|
|
1782
2004
|
this.page = null;
|
|
@@ -1784,6 +2006,9 @@
|
|
|
1784
2006
|
this.wrapperResizeObserver?.disconnect();
|
|
1785
2007
|
super.destroy();
|
|
1786
2008
|
}
|
|
2009
|
+
/**
|
|
2010
|
+
* 监听选中元素是否在画布可视区域内,如果目标元素不在可视区域内,通过滚动使该元素出现在可视区域
|
|
2011
|
+
*/
|
|
1787
2012
|
initObserverIntersection() {
|
|
1788
2013
|
this.pageScrollParent = getScrollParent(this.page) || null;
|
|
1789
2014
|
this.intersectionObserver?.disconnect();
|
|
@@ -1806,6 +2031,9 @@
|
|
|
1806
2031
|
);
|
|
1807
2032
|
}
|
|
1808
2033
|
}
|
|
2034
|
+
/**
|
|
2035
|
+
* 监听mask的容器大小变化
|
|
2036
|
+
*/
|
|
1809
2037
|
initObserverWrapper() {
|
|
1810
2038
|
this.wrapperResizeObserver?.disconnect();
|
|
1811
2039
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -1846,22 +2074,40 @@
|
|
|
1846
2074
|
});
|
|
1847
2075
|
this.content.dispatchEvent(event);
|
|
1848
2076
|
}
|
|
2077
|
+
/**
|
|
2078
|
+
* 设置蒙层高度
|
|
2079
|
+
* @param height 高度
|
|
2080
|
+
*/
|
|
1849
2081
|
setHeight(height) {
|
|
1850
2082
|
this.height = height;
|
|
1851
2083
|
this.setMaxScrollTop();
|
|
1852
2084
|
this.content.style.height = `${height}px`;
|
|
1853
2085
|
}
|
|
2086
|
+
/**
|
|
2087
|
+
* 设置蒙层宽度
|
|
2088
|
+
* @param width 宽度
|
|
2089
|
+
*/
|
|
1854
2090
|
setWidth(width) {
|
|
1855
2091
|
this.width = width;
|
|
1856
2092
|
this.setMaxScrollLeft();
|
|
1857
2093
|
this.content.style.width = `${width}px`;
|
|
1858
2094
|
}
|
|
2095
|
+
/**
|
|
2096
|
+
* 计算并设置最大滚动宽度
|
|
2097
|
+
*/
|
|
1859
2098
|
setMaxScrollLeft() {
|
|
1860
2099
|
this.maxScrollLeft = Math.max(this.width - this.wrapperWidth, 0);
|
|
1861
2100
|
}
|
|
2101
|
+
/**
|
|
2102
|
+
* 计算并设置最大滚动高度
|
|
2103
|
+
*/
|
|
1862
2104
|
setMaxScrollTop() {
|
|
1863
2105
|
this.maxScrollTop = Math.max(this.height - this.wrapperHeight, 0);
|
|
1864
2106
|
}
|
|
2107
|
+
/**
|
|
2108
|
+
* 修复滚动距离
|
|
2109
|
+
* 由于滚动容器变化等因素,会导致当前滚动的距离不正确
|
|
2110
|
+
*/
|
|
1865
2111
|
fixScrollValue() {
|
|
1866
2112
|
if (this.scrollTop < 0)
|
|
1867
2113
|
this.scrollTop = 0;
|
|
@@ -1874,7 +2120,7 @@
|
|
|
1874
2120
|
}
|
|
1875
2121
|
mouseWheelHandler = (event) => {
|
|
1876
2122
|
if (!this.page)
|
|
1877
|
-
throw new Error("page
|
|
2123
|
+
throw new Error("page 未初始化");
|
|
1878
2124
|
const { deltaY, deltaX } = event;
|
|
1879
2125
|
if (this.page.clientHeight < this.wrapperHeight && deltaY)
|
|
1880
2126
|
return;
|
|
@@ -1894,6 +2140,7 @@
|
|
|
1894
2140
|
const style = ".tmagic-stage-container-highlight::after {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n left: 0;\n background-color: #000;\n opacity: .1;\n pointer-events: none;\n}\n\n.magic-ui-container.magic-layout-relative {\n min-height: 50px;\n}\n";
|
|
1895
2141
|
|
|
1896
2142
|
class StageRender extends EventEmitter.EventEmitter {
|
|
2143
|
+
/** 组件的js、css执行的环境,直接渲染为当前window,iframe渲染则为iframe.contentWindow */
|
|
1897
2144
|
contentWindow = null;
|
|
1898
2145
|
runtime = null;
|
|
1899
2146
|
iframe;
|
|
@@ -1947,9 +2194,13 @@
|
|
|
1947
2194
|
setZoom(zoom = DEFAULT_ZOOM) {
|
|
1948
2195
|
this.zoom = zoom;
|
|
1949
2196
|
}
|
|
2197
|
+
/**
|
|
2198
|
+
* 挂载Dom节点
|
|
2199
|
+
* @param el 将页面挂载到该Dom节点上
|
|
2200
|
+
*/
|
|
1950
2201
|
async mount(el) {
|
|
1951
2202
|
if (!this.iframe) {
|
|
1952
|
-
throw Error("mount
|
|
2203
|
+
throw Error("mount 失败");
|
|
1953
2204
|
}
|
|
1954
2205
|
if (!utils.isSameDomain(this.runtimeUrl) && this.runtimeUrl) {
|
|
1955
2206
|
let html = await fetch(this.runtimeUrl).then((res) => res.text());
|
|
@@ -1975,6 +2226,11 @@
|
|
|
1975
2226
|
getDocument() {
|
|
1976
2227
|
return this.contentWindow?.document;
|
|
1977
2228
|
}
|
|
2229
|
+
/**
|
|
2230
|
+
* 通过坐标获得坐标下所有HTML元素数组
|
|
2231
|
+
* @param point 坐标
|
|
2232
|
+
* @returns 坐标下方所有HTML元素数组,会包含父元素直至html,元素层叠时返回顺序是从上到下
|
|
2233
|
+
*/
|
|
1978
2234
|
getElementsFromPoint(point) {
|
|
1979
2235
|
let x = point.clientX;
|
|
1980
2236
|
let y = point.clientY;
|
|
@@ -1991,11 +2247,14 @@
|
|
|
1991
2247
|
if (typeof idOrEl === "string" || typeof idOrEl === "number") {
|
|
1992
2248
|
const el = this.getDocument()?.getElementById(`${idOrEl}`);
|
|
1993
2249
|
if (!el)
|
|
1994
|
-
throw new Error(
|
|
2250
|
+
throw new Error(`不存在ID为${idOrEl}的元素`);
|
|
1995
2251
|
return el;
|
|
1996
2252
|
}
|
|
1997
2253
|
return idOrEl;
|
|
1998
2254
|
}
|
|
2255
|
+
/**
|
|
2256
|
+
* 销毁实例
|
|
2257
|
+
*/
|
|
1999
2258
|
destroy() {
|
|
2000
2259
|
this.iframe?.removeEventListener("load", this.loadHandler);
|
|
2001
2260
|
this.contentWindow = null;
|
|
@@ -2003,6 +2262,10 @@
|
|
|
2003
2262
|
this.iframe = void 0;
|
|
2004
2263
|
this.removeAllListeners();
|
|
2005
2264
|
}
|
|
2265
|
+
/**
|
|
2266
|
+
* 在runtime中对被选中的元素进行标记,部分组件有对选中态进行特殊显示的需求
|
|
2267
|
+
* @param el 被选中的元素
|
|
2268
|
+
*/
|
|
2006
2269
|
flagSelectedEl(el) {
|
|
2007
2270
|
const doc = this.getDocument();
|
|
2008
2271
|
if (doc) {
|
|
@@ -2065,6 +2328,10 @@
|
|
|
2065
2328
|
this.initActionEvent();
|
|
2066
2329
|
this.initMaskEvent();
|
|
2067
2330
|
}
|
|
2331
|
+
/**
|
|
2332
|
+
* 单选选中元素
|
|
2333
|
+
* @param idOrEl 选中的id或者元素
|
|
2334
|
+
*/
|
|
2068
2335
|
async select(idOrEl, event) {
|
|
2069
2336
|
const el = this.renderer.getTargetElement(idOrEl);
|
|
2070
2337
|
if (el === this.actionManager.getSelectedEl())
|
|
@@ -2076,6 +2343,10 @@
|
|
|
2076
2343
|
this.mask.observerIntersection(el);
|
|
2077
2344
|
}
|
|
2078
2345
|
}
|
|
2346
|
+
/**
|
|
2347
|
+
* 多选选中多个元素
|
|
2348
|
+
* @param idOrElList 选中元素的id或元素列表
|
|
2349
|
+
*/
|
|
2079
2350
|
async multiSelect(idOrElList) {
|
|
2080
2351
|
const els = idOrElList.map((idOrEl) => this.renderer.getTargetElement(idOrEl));
|
|
2081
2352
|
if (els.length === 0)
|
|
@@ -2089,9 +2360,17 @@
|
|
|
2089
2360
|
this.mask.observerIntersection(lastEl);
|
|
2090
2361
|
}
|
|
2091
2362
|
}
|
|
2363
|
+
/**
|
|
2364
|
+
* 高亮选中元素
|
|
2365
|
+
* @param el 要高亮的元素
|
|
2366
|
+
*/
|
|
2092
2367
|
highlight(idOrEl) {
|
|
2093
2368
|
this.actionManager.highlight(idOrEl);
|
|
2094
2369
|
}
|
|
2370
|
+
/**
|
|
2371
|
+
* 更新组件
|
|
2372
|
+
* @param data 更新组件的数据
|
|
2373
|
+
*/
|
|
2095
2374
|
async update(data) {
|
|
2096
2375
|
const { config } = data;
|
|
2097
2376
|
await this.renderer.update(data);
|
|
@@ -2104,15 +2383,27 @@
|
|
|
2104
2383
|
}
|
|
2105
2384
|
});
|
|
2106
2385
|
}
|
|
2386
|
+
/**
|
|
2387
|
+
* 往画布增加一个组件
|
|
2388
|
+
* @param data 组件信息数据
|
|
2389
|
+
*/
|
|
2107
2390
|
async add(data) {
|
|
2108
2391
|
return await this.renderer.add(data);
|
|
2109
2392
|
}
|
|
2393
|
+
/**
|
|
2394
|
+
* 从画布删除一个组件
|
|
2395
|
+
* @param data 组件信息数据
|
|
2396
|
+
*/
|
|
2110
2397
|
async remove(data) {
|
|
2111
2398
|
return await this.renderer.remove(data);
|
|
2112
2399
|
}
|
|
2113
2400
|
setZoom(zoom = DEFAULT_ZOOM) {
|
|
2114
2401
|
this.renderer.setZoom(zoom);
|
|
2115
2402
|
}
|
|
2403
|
+
/**
|
|
2404
|
+
* 挂载Dom节点
|
|
2405
|
+
* @param el 将stage挂载到该Dom节点上
|
|
2406
|
+
*/
|
|
2116
2407
|
async mount(el) {
|
|
2117
2408
|
this.container = el;
|
|
2118
2409
|
const { mask, renderer } = this;
|
|
@@ -2120,16 +2411,32 @@
|
|
|
2120
2411
|
mask.mount(el);
|
|
2121
2412
|
this.emit("mounted");
|
|
2122
2413
|
}
|
|
2414
|
+
/**
|
|
2415
|
+
* 清空所有参考线
|
|
2416
|
+
*/
|
|
2123
2417
|
clearGuides() {
|
|
2124
2418
|
this.mask.clearGuides();
|
|
2125
2419
|
this.actionManager.clearGuides();
|
|
2126
2420
|
}
|
|
2421
|
+
/**
|
|
2422
|
+
* @deprecated 废弃接口,建议用delayedMarkContainer代替
|
|
2423
|
+
*/
|
|
2127
2424
|
getAddContainerHighlightClassNameTimeout(event, excludeElList = []) {
|
|
2128
2425
|
return this.delayedMarkContainer(event, excludeElList);
|
|
2129
2426
|
}
|
|
2427
|
+
/**
|
|
2428
|
+
* 鼠标拖拽着元素,在容器上方悬停,延迟一段时间后,对容器进行标记,如果悬停时间够长将标记成功,悬停时间短,调用方通过返回的timeoutId取消标记
|
|
2429
|
+
* 标记的作用:1、高亮容器,给用户一个加入容器的交互感知;2、释放鼠标后,通过标记的标志找到要加入的容器
|
|
2430
|
+
* @param event 鼠标事件
|
|
2431
|
+
* @param excludeElList 计算鼠标所在容器时要排除的元素列表
|
|
2432
|
+
* @returns timeoutId,调用方在鼠标移走时要取消该timeout,阻止标记
|
|
2433
|
+
*/
|
|
2130
2434
|
delayedMarkContainer(event, excludeElList = []) {
|
|
2131
2435
|
return this.actionManager.delayedMarkContainer(event, excludeElList);
|
|
2132
2436
|
}
|
|
2437
|
+
/**
|
|
2438
|
+
* 销毁实例
|
|
2439
|
+
*/
|
|
2133
2440
|
destroy() {
|
|
2134
2441
|
const { mask, renderer, actionManager, pageResizeObserver } = this;
|
|
2135
2442
|
renderer.destroy();
|
|
@@ -2139,6 +2446,9 @@
|
|
|
2139
2446
|
this.removeAllListeners();
|
|
2140
2447
|
this.container = void 0;
|
|
2141
2448
|
}
|
|
2449
|
+
/**
|
|
2450
|
+
* 监听页面大小变化
|
|
2451
|
+
*/
|
|
2142
2452
|
observePageResize(page) {
|
|
2143
2453
|
if (typeof ResizeObserver !== "undefined") {
|
|
2144
2454
|
this.pageResizeObserver = new ResizeObserver((entries) => {
|
|
@@ -2182,12 +2492,18 @@
|
|
|
2182
2492
|
this.emit("change-guides", data);
|
|
2183
2493
|
});
|
|
2184
2494
|
}
|
|
2495
|
+
/**
|
|
2496
|
+
* 初始化操作相关事件监听
|
|
2497
|
+
*/
|
|
2185
2498
|
initActionEvent() {
|
|
2186
2499
|
this.initActionManagerEvent();
|
|
2187
2500
|
this.initDrEvent();
|
|
2188
2501
|
this.initMulDrEvent();
|
|
2189
2502
|
this.initHighlightEvent();
|
|
2190
2503
|
}
|
|
2504
|
+
/**
|
|
2505
|
+
* 初始化ActionManager类本身抛出来的事件监听
|
|
2506
|
+
*/
|
|
2191
2507
|
initActionManagerEvent() {
|
|
2192
2508
|
this.actionManager.on("before-select", (idOrEl, event) => {
|
|
2193
2509
|
this.select(idOrEl, event);
|
|
@@ -2199,6 +2515,9 @@
|
|
|
2199
2515
|
this.emit("multi-select", selectedElList);
|
|
2200
2516
|
});
|
|
2201
2517
|
}
|
|
2518
|
+
/**
|
|
2519
|
+
* 初始化DragResize类通过ActionManager抛出来的事件监听
|
|
2520
|
+
*/
|
|
2202
2521
|
initDrEvent() {
|
|
2203
2522
|
this.actionManager.on("update", (data) => {
|
|
2204
2523
|
this.emit("update", data);
|
|
@@ -2210,6 +2529,9 @@
|
|
|
2210
2529
|
this.emit("remove", data);
|
|
2211
2530
|
});
|
|
2212
2531
|
}
|
|
2532
|
+
/**
|
|
2533
|
+
* 初始化MultiDragResize类通过ActionManager抛出来的事件监听
|
|
2534
|
+
*/
|
|
2213
2535
|
initMulDrEvent() {
|
|
2214
2536
|
this.actionManager.on("change-to-select", (el) => {
|
|
2215
2537
|
this.select(el);
|
|
@@ -2218,6 +2540,9 @@
|
|
|
2218
2540
|
this.emit("update", data);
|
|
2219
2541
|
});
|
|
2220
2542
|
}
|
|
2543
|
+
/**
|
|
2544
|
+
* 初始化Highlight类通过ActionManager抛出来的事件监听
|
|
2545
|
+
*/
|
|
2221
2546
|
initHighlightEvent() {
|
|
2222
2547
|
this.actionManager.on("highlight", async (highlightEl) => {
|
|
2223
2548
|
this.emit("highlight", highlightEl);
|