@tmagic/stage 1.2.0-beta.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +62 -1
  2. package/dist/{tmagic-stage.mjs → tmagic-stage.js} +1395 -1062
  3. package/dist/tmagic-stage.js.map +1 -0
  4. package/dist/{tmagic-stage.umd.js → tmagic-stage.umd.cjs} +1393 -1060
  5. package/dist/tmagic-stage.umd.cjs.map +1 -0
  6. package/package.json +9 -8
  7. package/src/ActionManager.ts +535 -0
  8. package/src/DragResizeHelper.ts +338 -0
  9. package/src/MoveableOptionsManager.ts +249 -0
  10. package/src/MoveableSelectParentAble.ts +3 -5
  11. package/src/Rule.ts +4 -4
  12. package/src/StageCore.ts +203 -275
  13. package/src/StageDragResize.ts +86 -348
  14. package/src/StageHighlight.ts +17 -16
  15. package/src/StageMask.ts +19 -102
  16. package/src/StageMultiDragResize.ts +97 -198
  17. package/src/StageRender.ts +85 -10
  18. package/src/TargetShadow.ts +120 -0
  19. package/src/const.ts +1 -1
  20. package/src/types.ts +99 -19
  21. package/src/util.ts +18 -11
  22. package/types/ActionManager.d.ts +141 -0
  23. package/types/DragResizeHelper.d.ts +70 -0
  24. package/types/MoveableOptionsManager.d.ts +86 -0
  25. package/types/MoveableSelectParentAble.d.ts +1 -2
  26. package/types/StageCore.d.ts +58 -41
  27. package/types/StageDragResize.d.ts +12 -40
  28. package/types/StageHighlight.d.ts +3 -4
  29. package/types/StageMask.d.ts +0 -21
  30. package/types/StageMultiDragResize.d.ts +8 -24
  31. package/types/StageRender.d.ts +23 -4
  32. package/types/TargetShadow.d.ts +22 -0
  33. package/types/const.d.ts +1 -1
  34. package/types/types.d.ts +87 -18
  35. package/types/util.d.ts +8 -8
  36. package/dist/tmagic-stage.mjs.map +0 -1
  37. package/dist/tmagic-stage.umd.js.map +0 -1
  38. package/src/TargetCalibrate.ts +0 -119
  39. package/types/TargetCalibrate.d.ts +0 -20
@@ -0,0 +1,338 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making TMagicEditor available.
3
+ *
4
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import {
20
+ OnDrag,
21
+ OnDragGroup,
22
+ OnDragGroupStart,
23
+ OnDragStart,
24
+ OnResize,
25
+ OnResizeGroup,
26
+ OnResizeGroupStart,
27
+ OnResizeStart,
28
+ OnRotate,
29
+ OnRotateStart,
30
+ OnScale,
31
+ OnScaleStart,
32
+ } from 'moveable';
33
+ import MoveableHelper from 'moveable-helper';
34
+
35
+ import { DRAG_EL_ID_PREFIX, GHOST_EL_ID_PREFIX, Mode, ZIndex } from './const';
36
+ import TargetShadow from './TargetShadow';
37
+ import { DragResizeHelperConfig, TargetElement } from './types';
38
+ import { getAbsolutePosition, getOffset } from './util';
39
+
40
+ /**
41
+ * 拖拽/改变大小等操作发生时,moveable会抛出各种状态事件,DragResizeHelper负责响应这些事件,对目标节点target和拖拽节点targetShadow进行修改;
42
+ * 其中目标节点是DragResizeHelper直接改的,targetShadow作为直接被操作的拖拽框,是调用moveableHelper改的;
43
+ * 有个特殊情况是流式布局下,moveableHelper不支持,targetShadow也是DragResizeHelper直接改的
44
+ */
45
+ export default class DragResizeHelper {
46
+ /** 目标节点在蒙层上的占位节点,用于跟鼠标交互,避免鼠标事件直接作用到目标节点 */
47
+ private targetShadow: TargetShadow;
48
+ /** 要操作的原始目标节点 */
49
+ private target!: HTMLElement;
50
+ /** 多选:目标节点组 */
51
+ private targetList: HTMLElement[] = [];
52
+ /** 响应拖拽的状态事件,修改绝对定位布局下targetShadow的dom。
53
+ * MoveableHelper里面的方法是成员属性,如果DragResizeHelper用继承的方式将无法通过super去调这些方法 */
54
+ private moveableHelper: MoveableHelper;
55
+ /** 流式布局下,目标节点的镜像节点 */
56
+ private ghostEl: HTMLElement | undefined;
57
+ /** 用于记录节点被改变前的位置 */
58
+ private frameSnapShot = {
59
+ left: 0,
60
+ top: 0,
61
+ };
62
+ /** 多选模式下的多个节点 */
63
+ private framesSnapShot: { left: number; top: number; id: string }[] = [];
64
+ /** 布局方式:流式布局、绝对定位、固定定位 */
65
+ private mode: Mode = Mode.ABSOLUTE;
66
+
67
+ constructor(config: DragResizeHelperConfig) {
68
+ this.moveableHelper = MoveableHelper.create({
69
+ useBeforeRender: true,
70
+ useRender: false,
71
+ createAuto: true,
72
+ });
73
+
74
+ this.targetShadow = new TargetShadow({
75
+ container: config.container,
76
+ updateDragEl: config.updateDragEl,
77
+ zIndex: ZIndex.DRAG_EL,
78
+ idPrefix: DRAG_EL_ID_PREFIX,
79
+ });
80
+ }
81
+
82
+ public destroy(): void {
83
+ this.targetShadow.destroy();
84
+ this.destroyGhostEl();
85
+ this.moveableHelper.clear();
86
+ }
87
+
88
+ public destroyShadowEl(): void {
89
+ this.targetShadow.destroyEl();
90
+ }
91
+
92
+ public getShadowEl(): TargetElement | undefined {
93
+ return this.targetShadow.el;
94
+ }
95
+
96
+ public updateShadowEl(el: HTMLElement): void {
97
+ this.destroyGhostEl();
98
+ this.target = el;
99
+ this.targetShadow.update(el);
100
+ }
101
+
102
+ public setMode(mode: Mode): void {
103
+ this.mode = mode;
104
+ }
105
+
106
+ /**
107
+ * 改变大小事件开始
108
+ * @param e 包含了拖拽节点的dom,moveableHelper会直接修改拖拽节点
109
+ */
110
+ public onResizeStart(e: OnResizeStart): void {
111
+ this.moveableHelper.onResizeStart(e);
112
+
113
+ this.frameSnapShot.top = this.target.offsetTop;
114
+ this.frameSnapShot.left = this.target.offsetLeft;
115
+ }
116
+
117
+ public onResize(e: OnResize): void {
118
+ const { width, height, drag } = e;
119
+ const { beforeTranslate } = drag;
120
+ // 流式布局
121
+ if (this.mode === Mode.SORTABLE) {
122
+ this.target.style.top = '0px';
123
+ if (this.targetShadow.el) {
124
+ this.targetShadow.el.style.width = `${width}px`;
125
+ this.targetShadow.el.style.height = `${height}px`;
126
+ }
127
+ } else {
128
+ this.moveableHelper.onResize(e);
129
+ this.target.style.left = `${this.frameSnapShot.left + beforeTranslate[0]}px`;
130
+ this.target.style.top = `${this.frameSnapShot.top + beforeTranslate[1]}px`;
131
+ }
132
+
133
+ this.target.style.width = `${width}px`;
134
+ this.target.style.height = `${height}px`;
135
+ }
136
+
137
+ public onDragStart(e: OnDragStart): void {
138
+ this.moveableHelper.onDragStart(e);
139
+
140
+ if (this.mode === Mode.SORTABLE) {
141
+ this.ghostEl = this.generateGhostEl(this.target);
142
+ }
143
+
144
+ this.frameSnapShot.top = this.target.offsetTop;
145
+ this.frameSnapShot.left = this.target.offsetLeft;
146
+ }
147
+
148
+ public onDrag(e: OnDrag): void {
149
+ // 流式布局
150
+ if (this.ghostEl) {
151
+ this.ghostEl.style.top = `${this.frameSnapShot.top + e.beforeTranslate[1]}px`;
152
+ return;
153
+ }
154
+
155
+ this.moveableHelper.onDrag(e);
156
+
157
+ this.target.style.left = `${this.frameSnapShot.left + e.beforeTranslate[0]}px`;
158
+ this.target.style.top = `${this.frameSnapShot.top + e.beforeTranslate[1]}px`;
159
+ }
160
+
161
+ public onRotateStart(e: OnRotateStart): void {
162
+ this.moveableHelper.onRotateStart(e);
163
+ }
164
+
165
+ public onRotate(e: OnRotate): void {
166
+ this.moveableHelper.onRotate(e);
167
+ const frame = this.moveableHelper.getFrame(e.target);
168
+ this.target.style.transform = frame?.toCSSObject().transform || '';
169
+ }
170
+
171
+ public onScaleStart(e: OnScaleStart): void {
172
+ this.moveableHelper.onScaleStart(e);
173
+ }
174
+
175
+ public onScale(e: OnScale): void {
176
+ this.moveableHelper.onScale(e);
177
+ const frame = this.moveableHelper.getFrame(e.target);
178
+ this.target.style.transform = frame?.toCSSObject().transform || '';
179
+ }
180
+
181
+ public getGhostEl(): HTMLElement | undefined {
182
+ return this.ghostEl;
183
+ }
184
+
185
+ public destroyGhostEl(): void {
186
+ this.ghostEl?.remove();
187
+ this.ghostEl = undefined;
188
+ }
189
+
190
+ public clear(): void {
191
+ this.moveableHelper.clear();
192
+ }
193
+
194
+ public getFrame(el: HTMLElement | SVGElement): ReturnType<MoveableHelper['getFrame']> {
195
+ return this.moveableHelper.getFrame(el);
196
+ }
197
+
198
+ public getShadowEls(): TargetElement[] {
199
+ return this.targetShadow.els;
200
+ }
201
+
202
+ public updateGroup(els: HTMLElement[]): void {
203
+ this.targetList = els;
204
+ this.framesSnapShot = [];
205
+ this.targetShadow.updateGroup(els);
206
+ }
207
+
208
+ public setTargetList(targetList: HTMLElement[]): void {
209
+ this.targetList = targetList;
210
+ }
211
+
212
+ public clearMultiSelectStatus(): void {
213
+ this.targetList = [];
214
+ this.targetShadow.destroyEls();
215
+ }
216
+
217
+ public onResizeGroupStart(e: OnResizeGroupStart): void {
218
+ const { events } = e;
219
+ this.moveableHelper.onResizeGroupStart(e);
220
+ this.setFramesSnapShot(events);
221
+ }
222
+
223
+ /**
224
+ * 多选状态下通过拖拽边框改变大小,所有选中组件会一起改变大小
225
+ */
226
+ public onResizeGroup(e: OnResizeGroup): void {
227
+ const { events } = e;
228
+ // 拖动过程更新
229
+ events.forEach((ev) => {
230
+ const { width, height, beforeTranslate } = ev.drag;
231
+ const frameSnapShot = this.framesSnapShot.find(
232
+ (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
233
+ );
234
+ if (!frameSnapShot) return;
235
+ const targeEl = this.targetList.find(
236
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
237
+ );
238
+ if (!targeEl) return;
239
+ // 元素与其所属组同时加入多选列表时,只更新父元素
240
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
241
+
242
+ if (!isParentIncluded) {
243
+ // 更新页面元素位置
244
+ targeEl.style.left = `${frameSnapShot.left + beforeTranslate[0]}px`;
245
+ targeEl.style.top = `${frameSnapShot.top + beforeTranslate[1]}px`;
246
+ }
247
+
248
+ // 更新页面元素大小
249
+ targeEl.style.width = `${width}px`;
250
+ targeEl.style.height = `${height}px`;
251
+ });
252
+ this.moveableHelper.onResizeGroup(e);
253
+ }
254
+
255
+ public onDragGroupStart(e: OnDragGroupStart): void {
256
+ const { events } = e;
257
+ this.moveableHelper.onDragGroupStart(e);
258
+ // 记录拖动前快照
259
+ this.setFramesSnapShot(events);
260
+ }
261
+
262
+ public onDragGroup(e: OnDragGroup): void {
263
+ const { events } = e;
264
+ // 拖动过程更新
265
+ events.forEach((ev) => {
266
+ const frameSnapShot = this.framesSnapShot.find(
267
+ (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
268
+ );
269
+ if (!frameSnapShot) return;
270
+ const targeEl = this.targetList.find(
271
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
272
+ );
273
+ if (!targeEl) return;
274
+ // 元素与其所属组同时加入多选列表时,只更新父元素
275
+ const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
276
+ if (!isParentIncluded) {
277
+ // 更新页面元素位置
278
+ targeEl.style.left = `${frameSnapShot.left + ev.beforeTranslate[0]}px`;
279
+ targeEl.style.top = `${frameSnapShot.top + ev.beforeTranslate[1]}px`;
280
+ }
281
+ });
282
+ this.moveableHelper.onDragGroup(e);
283
+ }
284
+
285
+ /**
286
+ * 多选状态设置多个节点的快照
287
+ */
288
+ private setFramesSnapShot(events: OnDragStart[] | OnResizeStart[]): void {
289
+ // 同一组被选中的目标元素多次拖拽和改变大小会触发多次setFramesSnapShot,只有第一次可以设置成功
290
+ if (this.framesSnapShot.length > 0) return;
291
+ // 记录拖动前快照
292
+ events.forEach((ev) => {
293
+ // 实际目标元素
294
+ const matchEventTarget = this.targetList.find(
295
+ (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
296
+ );
297
+ if (!matchEventTarget) return;
298
+ this.framesSnapShot.push({
299
+ left: matchEventTarget.offsetLeft,
300
+ top: matchEventTarget.offsetTop,
301
+ id: matchEventTarget.id,
302
+ });
303
+ });
304
+ }
305
+
306
+ /**
307
+ * 流式布局把目标节点复制一份进行拖拽,在拖拽结束前不影响页面原布局样式
308
+ */
309
+ private generateGhostEl(el: HTMLElement): HTMLElement {
310
+ if (this.ghostEl) {
311
+ this.destroyGhostEl();
312
+ }
313
+
314
+ const ghostEl = el.cloneNode(true) as HTMLElement;
315
+ this.setGhostElChildrenId(ghostEl);
316
+ const { top, left } = getAbsolutePosition(el, getOffset(el));
317
+ ghostEl.id = `${GHOST_EL_ID_PREFIX}${el.id}`;
318
+ ghostEl.style.zIndex = ZIndex.GHOST_EL;
319
+ ghostEl.style.opacity = '.5';
320
+ ghostEl.style.position = 'absolute';
321
+ ghostEl.style.left = `${left}px`;
322
+ ghostEl.style.top = `${top}px`;
323
+ el.after(ghostEl);
324
+ return ghostEl;
325
+ }
326
+
327
+ private setGhostElChildrenId(el: Element): void {
328
+ for (const child of Array.from(el.children)) {
329
+ if (child.id) {
330
+ child.id = `${GHOST_EL_ID_PREFIX}${child.id}`;
331
+ }
332
+
333
+ if (child.children.length) {
334
+ this.setGhostElChildrenId(child);
335
+ }
336
+ }
337
+ }
338
+ }
@@ -0,0 +1,249 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making TMagicEditor available.
3
+ *
4
+ * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import EventEmitter from 'events';
20
+
21
+ import { merge } from 'lodash-es';
22
+ import { MoveableOptions } from 'moveable';
23
+
24
+ import { GuidesType, Mode } from './const';
25
+ import selectParentAbles from './MoveableSelectParentAble';
26
+ import { GetRootContainer, MoveableOptionsManagerConfig } from './types';
27
+ import { getOffset } from './util';
28
+
29
+ /**
30
+ * 单选和多选的父类,用于管理moveableOptions
31
+ * @extends EventEmitter
32
+ */
33
+ export default class MoveableOptionsManager extends EventEmitter {
34
+ /** 布局方式:流式布局、绝对定位、固定定位 */
35
+ public mode: Mode = Mode.ABSOLUTE;
36
+
37
+ /** 画布容器 */
38
+ protected container: HTMLElement;
39
+
40
+ /** 水平参考线 */
41
+ private horizontalGuidelines: number[] = [];
42
+ /** 垂直参考线 */
43
+ private verticalGuidelines: number[] = [];
44
+ /** 对齐元素集合 */
45
+ private elementGuidelines: HTMLElement[] = [];
46
+ /** 由外部调用方(编辑器)传入进来的moveable默认参数,可以为空,也可以是一个回调函数 */
47
+ private customizedOptions?: (() => MoveableOptions) | MoveableOptions;
48
+ /** 获取整个画布的根元素(在StageCore的mount函数中挂载的container) */
49
+ private getRootContainer: GetRootContainer;
50
+
51
+ constructor(config: MoveableOptionsManagerConfig) {
52
+ super();
53
+ this.customizedOptions = config.moveableOptions;
54
+ this.container = config.container;
55
+ this.getRootContainer = config.getRootContainer;
56
+ }
57
+
58
+ /**
59
+ * 设置水平/垂直参考线
60
+ * @param type 参考线类型
61
+ * @param guidelines 参考线坐标数组
62
+ */
63
+ public setGuidelines(type: GuidesType, guidelines: number[]): void {
64
+ if (type === GuidesType.HORIZONTAL) {
65
+ this.horizontalGuidelines = guidelines;
66
+ } else if (type === GuidesType.VERTICAL) {
67
+ this.verticalGuidelines = guidelines;
68
+ }
69
+
70
+ this.emit('update-moveable');
71
+ }
72
+
73
+ /**
74
+ * 清除横向和纵向的参考线
75
+ */
76
+ public clearGuides(): void {
77
+ this.horizontalGuidelines = [];
78
+ this.verticalGuidelines = [];
79
+
80
+ this.emit('update-moveable');
81
+ }
82
+
83
+ /**
84
+ * 设置有哪些元素要辅助对齐
85
+ * @param selectedElList 选中的元素列表,需要排除在对齐元素之外
86
+ * @param allElList 全部元素列表
87
+ */
88
+ protected setElementGuidelines(selectedElList: HTMLElement[], allElList: HTMLElement[]): void {
89
+ this.elementGuidelines.forEach((node) => {
90
+ node.remove();
91
+ });
92
+ this.elementGuidelines = [];
93
+
94
+ if (this.mode === Mode.ABSOLUTE) {
95
+ this.container.append(this.createGuidelineElements(selectedElList, allElList));
96
+ }
97
+ }
98
+
99
+ /**
100
+ * 获取moveable参数
101
+ * @param isMultiSelect 是否多选模式
102
+ * @param runtimeOptions 调用时实时传进来的的moveable参数
103
+ * @returns moveable所需参数
104
+ */
105
+ protected getOptions(isMultiSelect: boolean, runtimeOptions: MoveableOptions = {}): MoveableOptions {
106
+ const defaultOptions = this.getDefaultOptions(isMultiSelect);
107
+ const customizedOptions = this.getCustomizeOptions();
108
+
109
+ return merge(defaultOptions, customizedOptions, runtimeOptions);
110
+ }
111
+
112
+ /**
113
+ * 获取单选和多选的moveable公共参数
114
+ * @returns moveable公共参数
115
+ */
116
+ private getDefaultOptions(isMultiSelect: boolean): MoveableOptions {
117
+ const isSortable = this.mode === Mode.SORTABLE;
118
+
119
+ const commonOptions = {
120
+ draggable: true,
121
+ resizable: true,
122
+ rootContainer: this.getRootContainer(),
123
+ zoom: 1,
124
+ throttleDrag: 0,
125
+ snappable: true,
126
+ horizontalGuidelines: this.horizontalGuidelines,
127
+ verticalGuidelines: this.verticalGuidelines,
128
+ elementGuidelines: this.elementGuidelines,
129
+ bounds: {
130
+ top: 0,
131
+ // 设置0的话无法移动到left为0,所以只能设置为-1
132
+ left: -1,
133
+ right: this.container.clientWidth - 1,
134
+ bottom: isSortable ? undefined : this.container.clientHeight,
135
+ },
136
+ };
137
+ const differenceOptions = isMultiSelect ? this.getMultiOptions() : this.getSingleOptions();
138
+
139
+ return merge(commonOptions, differenceOptions);
140
+ }
141
+
142
+ /**
143
+ * 获取单选下的差异化参数
144
+ * @returns {MoveableOptions} moveable options参数
145
+ */
146
+ private getSingleOptions(): MoveableOptions {
147
+ const isAbsolute = this.mode === Mode.ABSOLUTE;
148
+ const isFixed = this.mode === Mode.FIXED;
149
+
150
+ return {
151
+ origin: false,
152
+ dragArea: false,
153
+ scalable: false,
154
+ rotatable: false,
155
+ snapGap: isAbsolute || isFixed,
156
+ snapThreshold: 5,
157
+ snapDigit: 0,
158
+ isDisplaySnapDigit: isAbsolute,
159
+ snapDirections: {
160
+ top: isAbsolute,
161
+ right: isAbsolute,
162
+ bottom: isAbsolute,
163
+ left: isAbsolute,
164
+ center: isAbsolute,
165
+ middle: isAbsolute,
166
+ },
167
+ elementSnapDirections: {
168
+ top: isAbsolute,
169
+ right: isAbsolute,
170
+ bottom: isAbsolute,
171
+ left: isAbsolute,
172
+ },
173
+ isDisplayInnerSnapDigit: true,
174
+
175
+ props: {
176
+ selectParent: true,
177
+ },
178
+
179
+ ables: [selectParentAbles(this.selectParentHandler.bind(this))],
180
+ };
181
+ }
182
+
183
+ /**
184
+ * 获取多选下的差异化参数
185
+ * @returns {MoveableOptions} moveable options参数
186
+ */
187
+ private getMultiOptions(): MoveableOptions {
188
+ return {
189
+ defaultGroupRotate: 0,
190
+ defaultGroupOrigin: '50% 50%',
191
+ startDragRotate: 0,
192
+ throttleDragRotate: 0,
193
+ origin: true,
194
+ padding: { left: 0, top: 0, right: 0, bottom: 0 },
195
+ };
196
+ }
197
+
198
+ /**
199
+ * 获取业务方自定义的moveable参数
200
+ */
201
+ private getCustomizeOptions(): MoveableOptions | undefined {
202
+ if (typeof this.customizedOptions === 'function') {
203
+ return this.customizedOptions();
204
+ }
205
+ return this.customizedOptions;
206
+ }
207
+
208
+ /**
209
+ * 这是给selectParentAbles的回调函数,用于触发选中父元素事件
210
+ */
211
+ private selectParentHandler(): void {
212
+ this.emit('select-parent');
213
+ }
214
+
215
+ /**
216
+ * 为需要辅助对齐的元素创建div
217
+ * @param selectedElList 选中的元素列表,需要排除在对齐元素之外
218
+ * @param allElList 全部元素列表
219
+ * @returns frame 辅助对齐元素集合的页面片
220
+ */
221
+ private createGuidelineElements(selectedElList: HTMLElement[], allElList: HTMLElement[]): DocumentFragment {
222
+ const frame = globalThis.document.createDocumentFragment();
223
+
224
+ for (const node of allElList) {
225
+ const { width, height } = node.getBoundingClientRect();
226
+ if (this.isInElementList(node, selectedElList)) continue;
227
+ const { left, top } = getOffset(node);
228
+ const elementGuideline = globalThis.document.createElement('div');
229
+ elementGuideline.style.cssText = `position: absolute;width: ${width}px;height: ${height}px;top: ${top}px;left: ${left}px`;
230
+ this.elementGuidelines.push(elementGuideline);
231
+ frame.append(elementGuideline);
232
+ }
233
+
234
+ return frame;
235
+ }
236
+
237
+ /**
238
+ * 判断一个元素是否在元素列表里面
239
+ * @param ele 元素
240
+ * @param eleList 元素列表
241
+ * @returns 是否在元素列表里面
242
+ */
243
+ private isInElementList(ele: HTMLElement, eleList: HTMLElement[]): boolean {
244
+ for (const eleItem of eleList) {
245
+ if (ele === eleItem) return true;
246
+ }
247
+ return false;
248
+ }
249
+ }
@@ -1,9 +1,7 @@
1
1
  import { MoveableManagerInterface, Renderer } from 'moveable';
2
2
 
3
- import type StageDragResize from './StageDragResize';
4
-
5
- export default (dr: StageDragResize) => ({
6
- name: 'selectParent',
3
+ export default (selectParentHandler: () => void) => ({
4
+ name: 'select-parent',
7
5
  props: {},
8
6
  events: {},
9
7
  render(moveable: MoveableManagerInterface<any, any>, React: Renderer) {
@@ -51,7 +49,7 @@ export default (dr: StageDragResize) => ({
51
49
  className: 'moveable-button',
52
50
  title: '选中父组件',
53
51
  onClick: () => {
54
- dr.emit('select-parent');
52
+ selectParentHandler();
55
53
  },
56
54
  },
57
55
  React.createElement(
package/src/Rule.ts CHANGED
@@ -60,12 +60,12 @@ export default class Rule extends EventEmitter {
60
60
  defaultGuides: vLines,
61
61
  });
62
62
 
63
- this.emit('changeGuides', {
63
+ this.emit('change-guides', {
64
64
  type: GuidesType.HORIZONTAL,
65
65
  guides: hLines,
66
66
  });
67
67
 
68
- this.emit('changeGuides', {
68
+ this.emit('change-guides', {
69
69
  type: GuidesType.VERTICAL,
70
70
  guides: vLines,
71
71
  });
@@ -143,7 +143,7 @@ export default class Rule extends EventEmitter {
143
143
 
144
144
  private hGuidesChangeGuidesHandler = (e: GuidesEvents['changeGuides']) => {
145
145
  this.horizontalGuidelines = e.guides;
146
- this.emit('changeGuides', {
146
+ this.emit('change-guides', {
147
147
  type: GuidesType.HORIZONTAL,
148
148
  guides: this.horizontalGuidelines,
149
149
  });
@@ -151,7 +151,7 @@ export default class Rule extends EventEmitter {
151
151
 
152
152
  private vGuidesChangeGuidesHandler = (e: GuidesEvents['changeGuides']) => {
153
153
  this.verticalGuidelines = e.guides;
154
- this.emit('changeGuides', {
154
+ this.emit('change-guides', {
155
155
  type: GuidesType.VERTICAL,
156
156
  guides: this.verticalGuidelines,
157
157
  });