jjb-lc-designable
Version:
基于alibaba-designable源码二次封装的表单设计器。
102 lines • 3.97 kB
JavaScript
import { EventDriver } from 'jjb-lc-designable/shared';
import { DragStartEvent, DragMoveEvent, DragStopEvent } from '../events';
const GlobalState = {
dragging: false,
onMouseDownAt: 0,
startEvent: null,
moveEvent: null
};
export class DragDropDriver extends EventDriver {
mouseDownTimer = null;
onMouseDown = e => {
if (e.button !== 0 || e.ctrlKey || e.metaKey) {
return;
}
if (e.target['isContentEditable'] || e.target['contentEditable'] === 'true') {
return true;
}
if (e.target?.['closest']?.('.monaco-editor')) return;
GlobalState.startEvent = e;
GlobalState.dragging = false;
GlobalState.onMouseDownAt = Date.now();
this.batchAddEventListener('mouseup', this.onMouseUp);
this.batchAddEventListener('dragend', this.onMouseUp);
this.batchAddEventListener('dragstart', this.onStartDrag);
this.batchAddEventListener('mousemove', this.onDistanceChange);
};
onMouseUp = e => {
if (GlobalState.dragging) {
this.dispatch(new DragStopEvent({
clientX: e.clientX,
clientY: e.clientY,
pageX: e.pageX,
pageY: e.pageY,
target: e.target,
view: e.view
}));
}
this.batchRemoveEventListener('contextmenu', this.onContextMenuWhileDragging, true);
this.batchRemoveEventListener('mouseup', this.onMouseUp);
this.batchRemoveEventListener('mousedown', this.onMouseDown);
this.batchRemoveEventListener('dragover', this.onMouseMove);
this.batchRemoveEventListener('mousemove', this.onMouseMove);
this.batchRemoveEventListener('mousemove', this.onDistanceChange);
GlobalState.dragging = false;
};
onMouseMove = e => {
if (e.clientX === GlobalState.moveEvent?.clientX && e.clientY === GlobalState.moveEvent?.clientY) return;
this.dispatch(new DragMoveEvent({
clientX: e.clientX,
clientY: e.clientY,
pageX: e.pageX,
pageY: e.pageY,
target: e.target,
view: e.view
}));
GlobalState.moveEvent = e;
};
onContextMenuWhileDragging = e => {
e.preventDefault();
};
onStartDrag = e => {
if (GlobalState.dragging) return;
GlobalState.startEvent = GlobalState.startEvent || e;
this.batchAddEventListener('dragover', this.onMouseMove);
this.batchAddEventListener('mousemove', this.onMouseMove);
this.batchAddEventListener('contextmenu', this.onContextMenuWhileDragging, true);
this.dispatch(new DragStartEvent({
clientX: GlobalState.startEvent.clientX,
clientY: GlobalState.startEvent.clientY,
pageX: GlobalState.startEvent.pageX,
pageY: GlobalState.startEvent.pageY,
target: GlobalState.startEvent.target,
view: GlobalState.startEvent.view
}));
GlobalState.dragging = true;
};
onDistanceChange = e => {
const distance = Math.sqrt(Math.pow(e.pageX - GlobalState.startEvent.pageX, 2) + Math.pow(e.pageY - GlobalState.startEvent.pageY, 2));
const timeDelta = Date.now() - GlobalState.onMouseDownAt;
if (timeDelta > 10 && e !== GlobalState.startEvent && distance > 4) {
this.batchRemoveEventListener('mousemove', this.onDistanceChange);
this.onStartDrag(e);
}
};
attach() {
this.batchAddEventListener('mousedown', this.onMouseDown, true);
}
detach() {
GlobalState.dragging = false;
GlobalState.moveEvent = null;
GlobalState.onMouseDownAt = null;
GlobalState.startEvent = null;
this.batchRemoveEventListener('mousedown', this.onMouseDown, true);
this.batchRemoveEventListener('dragstart', this.onStartDrag);
this.batchRemoveEventListener('dragend', this.onMouseUp);
this.batchRemoveEventListener('dragover', this.onMouseMove);
this.batchRemoveEventListener('mouseup', this.onMouseUp);
this.batchRemoveEventListener('mousemove', this.onMouseMove);
this.batchRemoveEventListener('mousemove', this.onDistanceChange);
this.batchRemoveEventListener('contextmenu', this.onContextMenuWhileDragging, true);
}
}