fix(stage): 优化拖拽体验,当选中的节点变化时,重新创建moveable,如果没有变化则update状态

This commit is contained in:
roymondchen 2022-04-07 15:20:09 +08:00 committed by jia000
parent fe4c0fa2dc
commit 39dcd89acf
3 changed files with 40 additions and 31 deletions

View File

@ -173,10 +173,12 @@ export default class StageCore extends EventEmitter {
// 更新配置后,需要等组件渲染更新 // 更新配置后,需要等组件渲染更新
setTimeout(() => { setTimeout(() => {
const el = this.renderer.contentWindow?.document.getElementById(`${config.id}`); 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是否可以滚动 // 更新了组件的布局需要重新设置mask是否可以滚动
this.mask.setLayout(el); this.mask.setLayout(el);
this.dr.select(el); this.dr.updateMoveable(el);
} }
}, 0); }, 0);
}); });

View File

@ -41,7 +41,7 @@ export default class StageDragResize extends EventEmitter {
public core: StageCore; public core: StageCore;
public container: HTMLElement; public container: HTMLElement;
public target?: HTMLElement; public target?: HTMLElement;
public dragEl?: HTMLElement; public dragEl: HTMLElement;
public moveable?: Moveable; public moveable?: Moveable;
public horizontalGuidelines: number[] = []; public horizontalGuidelines: number[] = [];
public verticalGuidelines: number[] = []; public verticalGuidelines: number[] = [];
@ -58,6 +58,9 @@ export default class StageDragResize extends EventEmitter {
this.core = config.core; this.core = config.core;
this.container = config.container; this.container = config.container;
this.dragEl = globalThis.document.createElement('div');
this.container.append(this.dragEl);
} }
/** /**
@ -67,25 +70,13 @@ export default class StageDragResize extends EventEmitter {
* @param event * @param event
*/ */
public select(el: HTMLElement, event?: MouseEvent): void { public select(el: HTMLElement, event?: MouseEvent): void {
const oldTarget = this.target;
this.target = el; this.target = el;
// 如果有滚动条会导致resize时获取到widthheight不准确
if (/(auto|scroll)/.test(this.target.style.overflow)) {
this.target.style.overflow = 'hidden';
}
this.mode = getMode(el);
this.destroyGhostEl(); this.init(el);
this.generateDragEl(el);
const originDraggable = this.moveableOptions.draggable;
this.moveableOptions = this.getOptions({
target: this.dragEl,
});
// 从不能拖动到能拖动的节点之间切换要重新创建moveable不然dragStart不生效 // 从不能拖动到能拖动的节点之间切换要重新创建moveable不然dragStart不生效
if (!this.moveable || originDraggable !== this.moveableOptions.draggable) { if (!this.moveable || this.target !== oldTarget) {
this.moveableHelper = MoveableHelper.create({ this.moveableHelper = MoveableHelper.create({
useBeforeRender: true, useBeforeRender: true,
useRender: false, useRender: false,
@ -94,7 +85,7 @@ export default class StageDragResize extends EventEmitter {
this.initMoveable(); this.initMoveable();
} else { } else {
this.refresh(); this.updateMoveable();
} }
if (event) { if (event) {
@ -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 (!this.moveable) throw new Error('未初始化moveable');
if (!el) throw new Error('为选中任何节点');
this.target = el;
this.init(el);
Object.entries(this.moveableOptions).forEach(([key, value]) => { Object.entries(this.moveableOptions).forEach(([key, value]) => {
(this.moveable as any)[key] = value; (this.moveable as any)[key] = value;
@ -123,7 +119,7 @@ export default class StageDragResize extends EventEmitter {
this.moveableOptions.verticalGuidelines = guidelines; this.moveableOptions.verticalGuidelines = guidelines;
} }
this.refresh(); this.updateMoveable();
} }
public clearGuides() { public clearGuides() {
@ -131,7 +127,7 @@ export default class StageDragResize extends EventEmitter {
this.verticalGuidelines = []; this.verticalGuidelines = [];
this.moveableOptions.horizontalGuidelines = []; this.moveableOptions.horizontalGuidelines = [];
this.moveableOptions.verticalGuidelines = []; this.moveableOptions.verticalGuidelines = [];
this.refresh(); this.updateMoveable();
} }
/** /**
@ -145,6 +141,22 @@ export default class StageDragResize extends EventEmitter {
this.removeAllListeners(); this.removeAllListeners();
} }
private init(el: HTMLElement): void {
// 如果有滚动条会导致resize时获取到widthheight不准确
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() { private initMoveable() {
this.moveable?.destroy(); this.moveable?.destroy();
@ -332,15 +344,10 @@ export default class StageDragResize extends EventEmitter {
this.ghostEl = undefined; this.ghostEl = undefined;
} }
private generateDragEl(el: HTMLElement) { private updateDragEl(el: HTMLElement) {
const { width, height } = el.getBoundingClientRect(); const { width, height } = el.getBoundingClientRect();
const offset = getOffset(el); const offset = getOffset(el);
if (!this.dragEl) {
this.dragEl = globalThis.document.createElement('div');
this.container.append(this.dragEl);
}
this.dragEl.style.cssText = ` this.dragEl.style.cssText = `
position: absolute; position: absolute;
left: ${offset.left}px; left: ${offset.left}px;
@ -354,7 +361,6 @@ export default class StageDragResize extends EventEmitter {
private destroyDragEl(): void { private destroyDragEl(): void {
this.dragEl?.remove(); this.dragEl?.remove();
this.dragEl = undefined;
} }
private getOptions(options: MoveableOptions = {}): MoveableOptions { private getOptions(options: MoveableOptions = {}): MoveableOptions {

View File

@ -25,7 +25,7 @@ import type { StageMaskConfig } from './types';
import { createDiv, getScrollParent, isFixedParent } from './util'; import { createDiv, getScrollParent, isFixedParent } from './util';
const wrapperClassName = 'editor-mask-wrapper'; const wrapperClassName = 'editor-mask-wrapper';
const throttleTime = 100; const throttleTime = 300;
const hideScrollbar = () => { const hideScrollbar = () => {
const style = globalThis.document.createElement('style'); const style = globalThis.document.createElement('style');
@ -215,6 +215,8 @@ export default class StageMask extends Rule {
* @param event * @param event
*/ */
private mouseDownHandler = (event: MouseEvent): void => { private mouseDownHandler = (event: MouseEvent): void => {
this.emit('clearHighlight');
event.stopImmediatePropagation(); event.stopImmediatePropagation();
event.stopPropagation(); event.stopPropagation();
@ -226,7 +228,6 @@ export default class StageMask extends Rule {
} }
this.content.removeEventListener('mousemove', this.highlightHandler); this.content.removeEventListener('mousemove', this.highlightHandler);
this.emit('clearHighlight');
this.emit('beforeSelect', event); this.emit('beforeSelect', event);