Skip to content

Commit

Permalink
fix(stage): 优化拖拽体验,当选中的节点变化时,重新创建moveable,如果没有变化则update状态
Browse files Browse the repository at this point in the history
  • Loading branch information
roymondchen authored and jia000 committed Apr 7, 2022
1 parent fe4c0fa commit 39dcd89
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 31 deletions.
6 changes: 4 additions & 2 deletions packages/stage/src/StageCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,12 @@ export default class StageCore extends EventEmitter {
// 更新配置后,需要等组件渲染更新
setTimeout(() => {
const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`);
if (el) {
// 有可能dom已经重新渲染,不再是原来的dom了,所以这里判断id,而不是判断el === this.selectedDom
if (el && el.id === this.selectedDom?.id) {
this.selectedDom = el;
// 更新了组件的布局,需要重新设置mask是否可以滚动
this.mask.setLayout(el);
this.dr.select(el);
this.dr.updateMoveable(el);
}
}, 0);
});
Expand Down
60 changes: 33 additions & 27 deletions packages/stage/src/StageDragResize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class StageDragResize extends EventEmitter {
public core: StageCore;
public container: HTMLElement;
public target?: HTMLElement;
public dragEl?: HTMLElement;
public dragEl: HTMLElement;
public moveable?: Moveable;
public horizontalGuidelines: number[] = [];
public verticalGuidelines: number[] = [];
Expand All @@ -58,6 +58,9 @@ export default class StageDragResize extends EventEmitter {

this.core = config.core;
this.container = config.container;

this.dragEl = globalThis.document.createElement('div');
this.container.append(this.dragEl);
}

/**
Expand All @@ -67,25 +70,13 @@ export default class StageDragResize extends EventEmitter {
* @param event 鼠标事件
*/
public select(el: HTMLElement, event?: MouseEvent): void {
const oldTarget = this.target;
this.target = el;
// 如果有滚动条会导致resize时获取到width,height不准确
if (/(auto|scroll)/.test(this.target.style.overflow)) {
this.target.style.overflow = 'hidden';
}
this.mode = getMode(el);

this.destroyGhostEl();

this.generateDragEl(el);

const originDraggable = this.moveableOptions.draggable;

this.moveableOptions = this.getOptions({
target: this.dragEl,
});
this.init(el);

// 从不能拖动到能拖动的节点之间切换,要重新创建moveable,不然dragStart不生效
if (!this.moveable || originDraggable !== this.moveableOptions.draggable) {
if (!this.moveable || this.target !== oldTarget) {
this.moveableHelper = MoveableHelper.create({
useBeforeRender: true,
useRender: false,
Expand All @@ -94,7 +85,7 @@ export default class StageDragResize extends EventEmitter {

this.initMoveable();
} else {
this.refresh();
this.updateMoveable();
}

if (event) {
Expand All @@ -105,8 +96,13 @@ export default class StageDragResize extends EventEmitter {
/**
* 初始化选中框并渲染出来
*/
public refresh() {
public updateMoveable(el = this.target): void {
if (!this.moveable) throw new Error('未初始化moveable');
if (!el) throw new Error('为选中任何节点');

this.target = el;

this.init(el);

Object.entries(this.moveableOptions).forEach(([key, value]) => {
(this.moveable as any)[key] = value;
Expand All @@ -123,15 +119,15 @@ export default class StageDragResize extends EventEmitter {
this.moveableOptions.verticalGuidelines = guidelines;
}

this.refresh();
this.updateMoveable();
}

public clearGuides() {
this.horizontalGuidelines = [];
this.verticalGuidelines = [];
this.moveableOptions.horizontalGuidelines = [];
this.moveableOptions.verticalGuidelines = [];
this.refresh();
this.updateMoveable();
}

/**
Expand All @@ -145,6 +141,22 @@ export default class StageDragResize extends EventEmitter {
this.removeAllListeners();
}

private init(el: HTMLElement): void {
// 如果有滚动条会导致resize时获取到width,height不准确
if (/(auto|scroll)/.test(el.style.overflow)) {
el.style.overflow = 'hidden';
}
this.mode = getMode(el);

this.destroyGhostEl();

this.updateDragEl(el);

this.moveableOptions = this.getOptions({
target: this.dragEl,
});
}

private initMoveable() {
this.moveable?.destroy();

Expand Down Expand Up @@ -332,15 +344,10 @@ export default class StageDragResize extends EventEmitter {
this.ghostEl = undefined;
}

private generateDragEl(el: HTMLElement) {
private updateDragEl(el: HTMLElement) {
const { width, height } = el.getBoundingClientRect();
const offset = getOffset(el);

if (!this.dragEl) {
this.dragEl = globalThis.document.createElement('div');
this.container.append(this.dragEl);
}

this.dragEl.style.cssText = `
position: absolute;
left: ${offset.left}px;
Expand All @@ -354,7 +361,6 @@ export default class StageDragResize extends EventEmitter {

private destroyDragEl(): void {
this.dragEl?.remove();
this.dragEl = undefined;
}

private getOptions(options: MoveableOptions = {}): MoveableOptions {
Expand Down
5 changes: 3 additions & 2 deletions packages/stage/src/StageMask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type { StageMaskConfig } from './types';
import { createDiv, getScrollParent, isFixedParent } from './util';

const wrapperClassName = 'editor-mask-wrapper';
const throttleTime = 100;
const throttleTime = 300;

const hideScrollbar = () => {
const style = globalThis.document.createElement('style');
Expand Down Expand Up @@ -215,6 +215,8 @@ export default class StageMask extends Rule {
* @param event 事件对象
*/
private mouseDownHandler = (event: MouseEvent): void => {
this.emit('clearHighlight');

event.stopImmediatePropagation();
event.stopPropagation();

Expand All @@ -226,7 +228,6 @@ export default class StageMask extends Rule {
}

this.content.removeEventListener('mousemove', this.highlightHandler);
this.emit('clearHighlight');

this.emit('beforeSelect', event);

Expand Down

0 comments on commit 39dcd89

Please sign in to comment.