UNPKG

@logicflow/core

Version:

LogicFlow, help you quickly create flowcharts

220 lines (189 loc) 6.12 kB
import { noop } from 'lodash-es' import { Model } from '../model' import { EventType } from '../constant' import EventEmitter from '../event/eventEmitter' // TODO:这种方式在同构项目中,会报错,该如何解决(是否要求用户控制在浏览器环境时才初始化) // const DOC: any = window?.document const LEFT_MOUSE_BUTTON_CODE = 0 export type IDragParams = { deltaX: number deltaY: number event: MouseEvent | null [key: string]: unknown } export type ICreateDragParams = { onDragStart?: (params: Partial<IDragParams>) => void onDragging?: (param: IDragParams) => void onDragEnd?: (param: Partial<IDragParams>) => void step?: number isStopPropagation?: boolean } export type IStepperDragProps = { eventType?: | 'NODE' | 'BLANK' | 'SELECTION' | 'ADJUST_POINT' | 'TEXT' | 'LABEL' | '' eventCenter?: EventEmitter model?: Model.BaseModel data?: Record<string, unknown> [key: string]: unknown } & Partial<ICreateDragParams> /** * 支持拖拽时按步长进行移动 * REMIND:在绘制的过程中因为放大缩小,移动的真实 step 是变化的 */ export class StepperDrag { // 初始化 onDragStart: (params: Partial<IDragParams>) => void onDragging: (params: IDragParams) => void onDragEnd: (params: Partial<IDragParams>) => void step: number isStopPropagation: boolean eventType: | 'NODE' | 'BLANK' | 'SELECTION' | 'ADJUST_POINT' | 'TEXT' | 'LABEL' | '' eventCenter?: EventEmitter model?: Model.BaseModel data?: Record<string, unknown> // 运行时 isDragging: boolean = false isStartDrag: boolean = false startX: number = 0 startY: number = 0 totalDeltaX: number = 0 totalDeltaY: number = 0 startTime?: number constructor({ onDragStart = noop, onDragging = noop, onDragEnd = noop, step = 1, eventType = '', isStopPropagation = true, eventCenter, model, data, }: IStepperDragProps) { this.onDragStart = onDragStart this.onDragging = onDragging this.onDragEnd = onDragEnd this.step = step this.eventType = eventType this.isStopPropagation = isStopPropagation this.eventCenter = eventCenter this.model = model this.data = data } setStep(step: number) { this.step = step } handleMouseMove = (e: MouseEvent) => { if (this.isStopPropagation) e.stopPropagation() if (!this.isStartDrag) return this.totalDeltaX += e.clientX - this.startX this.totalDeltaY += e.clientY - this.startY this.startX = e.clientX this.startY = e.clientY if ( this.step <= 1 || Math.abs(this.totalDeltaX) > this.step || Math.abs(this.totalDeltaY) > this.step ) { const remainderX = this.totalDeltaX % this.step const remainderY = this.totalDeltaY % this.step const deltaX = this.totalDeltaX - remainderX const deltaY = this.totalDeltaY - remainderY this.totalDeltaX = remainderX this.totalDeltaY = remainderY const elementData = this.model?.getData() // REMIND: 为了区分点击和拖动,在鼠标没有拖动时,不触发 dragstart。 if (!this.isDragging) { if (this.eventType) { this.eventCenter?.emit(EventType[`${this.eventType}_DRAGSTART`], { e, data: this.data || elementData, }) } this.onDragStart({ event: e }) } this.isDragging = true // REMIND: 为了让 dragstart 和 drag 不在同一个事件循环中,将 drag 事件放在下一个任务队列中。 // TODO: 测试用例是否可覆盖??? Promise.resolve().then(() => { this.onDragging({ deltaX, deltaY, event: e }) if (this.eventType) { this.eventCenter?.emit(EventType[`${this.eventType}_MOUSEMOVE`], { e, data: this.data || elementData, }) this.eventCenter?.emit(EventType[`${this.eventType}_DRAG`], { e, data: this.data || elementData, }) } }) } } handleMouseUp = (e: MouseEvent) => { const DOC: any = window?.document this.isStartDrag = false if (this.isStopPropagation) e.stopPropagation() // fix: issue#568, 如果 onDragging 在下一个时间循环中触发,而 drop 在当前事件循环,会出现问题 Promise.resolve().then(() => { DOC?.removeEventListener('mousemove', this.handleMouseMove, true) DOC?.removeEventListener('mouseup', this.handleMouseUp, true) const elementData = this.model?.getData() if (this.eventType) { this.eventCenter?.emit(EventType[`${this.eventType}_MOUSEUP`], { e, data: this.data || elementData, }) } if (!this.isDragging) return this.isDragging = false this.onDragEnd({ event: e }) if (this.eventType) { this.eventCenter?.emit(EventType[`${this.eventType}_DROP`], { e, data: this.data || elementData, }) } }) } handleMouseDown = (e: MouseEvent) => { const DOC: any = window?.document // issue: LogicFlow交流群-3群 8.10 号抛出的事件相关的问题,是否是这引起的??? if (e.button !== LEFT_MOUSE_BUTTON_CODE) return if (this.isStopPropagation) e.stopPropagation() this.isStartDrag = true this.startX = e.clientX this.startY = e.clientY DOC?.addEventListener('mousemove', this.handleMouseMove, true) DOC?.addEventListener('mouseup', this.handleMouseUp, true) const elementData = this.model?.getData() if (this.eventType) { this.eventCenter?.emit(EventType[`${this.eventType}_MOUSEDOWN`], { e, data: this.data || elementData, }) } this.startTime = new Date().getTime() } cancelDrag = () => { const DOC: any = window?.document DOC?.removeEventListener('mousemove', this.handleMouseMove, true) DOC?.removeEventListener('mouseup', this.handleMouseUp, true) this.onDragEnd({ event: null }) this.isDragging = false } } export default StepperDrag