mirror of
				https://github.com/Tencent/tmagic-editor.git
				synced 2025-11-04 10:49:51 +08:00 
			
		
		
		
	多选优化及问题修复 (#196)
* feat(stage): 支持绝对定位,固定定位,组内元素按住shift键进行多选拖拽能力 * feat(stage): 使用moveable.helper接管moveable target的更新,针对弹窗场景引入业务方方法进行校准 * feat(stage): 将多选逻辑封装到StageMultiDragResize * fix(stage): 修复多选target元素无法映射到drag虚拟元素的问题 * feat(stage): 多选拖拽完成后将更新的位置信息暴露给上层业务方 * fix(stage): 删除多余的成员变量 Co-authored-by: parisma <parisma@tencent.com>
This commit is contained in:
		
							parent
							
								
									fe520bf600
								
							
						
					
					
						commit
						3ccabfbe44
					
				@ -141,6 +141,10 @@ export default class StageCore extends EventEmitter {
 | 
			
		||||
      .on('sort', (data: UpdateEventData) => {
 | 
			
		||||
        setTimeout(() => this.emit('sort', data));
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    this.multiDr.on('update', (data: UpdateEventData) => {
 | 
			
		||||
      setTimeout(() => this.emit('update', data));
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getElementsFromPoint(event: MouseEvent) {
 | 
			
		||||
 | 
			
		||||
@ -53,14 +53,8 @@ export default class StageDragResize extends EventEmitter {
 | 
			
		||||
  public target?: HTMLElement;
 | 
			
		||||
  /** 目标节点在蒙层中的占位节点 */
 | 
			
		||||
  public dragEl?: HTMLDivElement;
 | 
			
		||||
  /** 多选:目标节点组 */
 | 
			
		||||
  public targetList: HTMLElement[] = [];
 | 
			
		||||
  /** 多选:目标节点在蒙层中的占位节点组 */
 | 
			
		||||
  public dragElList: HTMLDivElement[] = [];
 | 
			
		||||
  /** Moveable拖拽类实例 */
 | 
			
		||||
  public moveable?: Moveable;
 | 
			
		||||
  /** Moveable多选拖拽类实例 */
 | 
			
		||||
  public moveableForMulti?: Moveable;
 | 
			
		||||
  /** 水平参考线 */
 | 
			
		||||
  public horizontalGuidelines: number[] = [];
 | 
			
		||||
  /** 垂直参考线 */
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ import { DRAG_EL_ID_PREFIX } from './const';
 | 
			
		||||
import StageCore from './StageCore';
 | 
			
		||||
import StageMask from './StageMask';
 | 
			
		||||
import { StageDragResizeConfig } from './types';
 | 
			
		||||
import { getTargetElStyle } from './util';
 | 
			
		||||
import { calcValueByFontsize, getTargetElStyle } from './util';
 | 
			
		||||
export default class StageMultiDragResize extends EventEmitter {
 | 
			
		||||
  public core: StageCore;
 | 
			
		||||
  public mask: StageMask;
 | 
			
		||||
@ -88,7 +88,7 @@ export default class StageMultiDragResize extends EventEmitter {
 | 
			
		||||
      useRender: false,
 | 
			
		||||
      createAuto: true,
 | 
			
		||||
    });
 | 
			
		||||
    const frames: { left: number; top: number; dragLeft: number; dragTop: number; id: string }[] = [];
 | 
			
		||||
    const frames: { left: number; top: number; id: string }[] = [];
 | 
			
		||||
    this.moveableForMulti
 | 
			
		||||
      .on('dragGroupStart', (params) => {
 | 
			
		||||
        const { events } = params;
 | 
			
		||||
@ -96,15 +96,13 @@ export default class StageMultiDragResize extends EventEmitter {
 | 
			
		||||
        // 记录拖动前快照
 | 
			
		||||
        events.forEach((ev) => {
 | 
			
		||||
          // 实际目标元素
 | 
			
		||||
          const matchEventTarget = this.targetList.find((targetItem) => targetItem.id === ev.target.id.split('_')[2]);
 | 
			
		||||
          // 蒙层虚拟元素(对于在组内的元素拖动时的相对位置不同,因此需要分别记录)
 | 
			
		||||
          const dragEventTarget = ev.target as HTMLDivElement;
 | 
			
		||||
          if (!matchEventTarget || !dragEventTarget) return;
 | 
			
		||||
          const matchEventTarget = this.targetList.find(
 | 
			
		||||
            (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
 | 
			
		||||
          );
 | 
			
		||||
          if (!matchEventTarget) return;
 | 
			
		||||
          frames.push({
 | 
			
		||||
            left: matchEventTarget.offsetLeft,
 | 
			
		||||
            top: matchEventTarget.offsetTop,
 | 
			
		||||
            dragLeft: dragEventTarget.offsetLeft,
 | 
			
		||||
            dragTop: dragEventTarget.offsetTop,
 | 
			
		||||
            id: matchEventTarget.id,
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
@ -113,9 +111,13 @@ export default class StageMultiDragResize extends EventEmitter {
 | 
			
		||||
        const { events } = params;
 | 
			
		||||
        // 拖动过程更新
 | 
			
		||||
        events.forEach((ev) => {
 | 
			
		||||
          const frameSnapShot = frames.find((frameItem) => frameItem.id === ev.target.id.split('_')[2]);
 | 
			
		||||
          const frameSnapShot = frames.find(
 | 
			
		||||
            (frameItem) => frameItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
 | 
			
		||||
          );
 | 
			
		||||
          if (!frameSnapShot) return;
 | 
			
		||||
          const targeEl = this.targetList.find((targetItem) => targetItem.id === ev.target.id.split('_')[2]);
 | 
			
		||||
          const targeEl = this.targetList.find(
 | 
			
		||||
            (targetItem) => targetItem.id === ev.target.id.replace(DRAG_EL_ID_PREFIX, ''),
 | 
			
		||||
          );
 | 
			
		||||
          if (!targeEl) return;
 | 
			
		||||
          // 元素与其所属组同时加入多选列表时,只更新父元素
 | 
			
		||||
          const isParentIncluded = this.targetList.find((targetItem) => targetItem.id === targeEl.parentElement?.id);
 | 
			
		||||
@ -126,6 +128,9 @@ export default class StageMultiDragResize extends EventEmitter {
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        this.multiMoveableHelper?.onDragGroup(params);
 | 
			
		||||
      })
 | 
			
		||||
      .on('dragGroupEnd', () => {
 | 
			
		||||
        this.update();
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -153,4 +158,28 @@ export default class StageMultiDragResize extends EventEmitter {
 | 
			
		||||
  public destroyDragElList(): void {
 | 
			
		||||
    this.dragElList.forEach((dragElItem) => dragElItem?.remove());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 拖拽完成后将更新的位置信息暴露给上层业务方,业务方可以接收事件进行保存
 | 
			
		||||
   * @param isResize 是否进行大小缩放
 | 
			
		||||
   */
 | 
			
		||||
  private update(isResize = false): void {
 | 
			
		||||
    if (this.targetList.length === 0) return;
 | 
			
		||||
 | 
			
		||||
    const { contentWindow } = this.core.renderer;
 | 
			
		||||
    const doc = contentWindow?.document;
 | 
			
		||||
    if (!doc) return;
 | 
			
		||||
 | 
			
		||||
    this.targetList.forEach((targetItem) => {
 | 
			
		||||
      const offset = { left: targetItem.offsetLeft, top: targetItem.offsetTop };
 | 
			
		||||
      const left = calcValueByFontsize(doc, offset.left);
 | 
			
		||||
      const top = calcValueByFontsize(doc, offset.top);
 | 
			
		||||
      const width = calcValueByFontsize(doc, targetItem.clientWidth);
 | 
			
		||||
      const height = calcValueByFontsize(doc, targetItem.clientHeight);
 | 
			
		||||
      this.emit('update', {
 | 
			
		||||
        el: targetItem,
 | 
			
		||||
        style: isResize ? { left, top, width, height } : { left, top },
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user