Skip to content

Commit

Permalink
perf: 完善对象
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBeard30 committed Mar 12, 2024
1 parent d08cfc9 commit 04bc508
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 0 deletions.
116 changes: 116 additions & 0 deletions src/app/core/drivers/drag-drop-driver.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,124 @@
import { EventDriver } from '../../shared/event';
import { Engine } from '../models';
import { DragMoveEvent, DragStartEvent, DragStopEvent } from '../events/cursor';

const GlobalState = {
dragging: false,
onMouseDownAt: 0,
startEvent: null,
moveEvent: null
};

export class DragDropDriver extends EventDriver<Engine> {
mouseDownTimer = null;

startEvent: MouseEvent;

onMouseDown = (e: MouseEvent) => {
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);
return;
};

onMouseUp = (e: MouseEvent) => {
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: MouseEvent | DragEvent) => {
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: MouseEvent) => {
e.preventDefault();
};

onStartDrag = (e: MouseEvent | DragEvent) => {
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: MouseEvent) => {
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);
}
};

override attach() {
this.batchAddEventListener('mousedown', this.onMouseDown, true);
}

override 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);
}
}
57 changes: 57 additions & 0 deletions src/app/core/events/cursor/AbstractCursorEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { IEngineContext } from '../../types';
import { globalThisPolyfill } from '../../../shared/globalThisPolyfill';

export interface ICursorEventOriginData {
clientX: number;
clientY: number;
pageX: number;
pageY: number;
target: EventTarget;
view: Window;
}

export interface ICursorEventData extends ICursorEventOriginData {
topClientX?: number;
topClientY?: number;
topPageX?: number;
topPageY?: number;
}

export class AbstractCursorEvent {
data: ICursorEventData;

context: IEngineContext;

constructor(data: ICursorEventOriginData) {
this.data = data || {
clientX: 0,
clientY: 0,
pageX: 0,
pageY: 0,
target: null,
view: globalThisPolyfill
};
this.transformCoordinates();
}

transformCoordinates() {
const { frameElement } = this.data?.view || {};
if (frameElement && this.data.view !== globalThisPolyfill) {
const frameRect = frameElement.getBoundingClientRect();
const scale = frameRect.width / frameElement['offsetWidth'];
this.data.topClientX = this.data.clientX * scale + frameRect.x;
this.data.topClientY = this.data.clientY * scale + frameRect.y;
this.data.topPageX = this.data.pageX + frameRect.x - this.data.view.scrollX;
this.data.topPageY = this.data.pageY + frameRect.y - this.data.view.scrollY;
const topElement = document.elementFromPoint(this.data.topPageX, this.data.topClientY);
if (topElement !== frameElement) {
this.data.target = topElement;
}
} else {
this.data.topClientX = this.data.clientX;
this.data.topClientY = this.data.clientY;
this.data.topPageX = this.data.pageX;
this.data.topPageY = this.data.pageY;
}
}
}
6 changes: 6 additions & 0 deletions src/app/core/events/cursor/DragMoveEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AbstractCursorEvent } from './AbstractCursorEvent';
import { ICustomEvent } from '../../../shared/event';

export class DragMoveEvent extends AbstractCursorEvent implements ICustomEvent {
type = 'drag:move';
}
6 changes: 6 additions & 0 deletions src/app/core/events/cursor/DragStartEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AbstractCursorEvent } from './AbstractCursorEvent';
import { ICustomEvent } from '../../../shared/event';

export class DragStartEvent extends AbstractCursorEvent implements ICustomEvent {
type = 'drag:start';
}
6 changes: 6 additions & 0 deletions src/app/core/events/cursor/DragStopEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AbstractCursorEvent } from './AbstractCursorEvent';
import { ICustomEvent } from '../../../shared/event';

export class DragStopEvent extends AbstractCursorEvent implements ICustomEvent {
type = 'drag:stop';
}
10 changes: 10 additions & 0 deletions src/app/core/events/cursor/MouseClickEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { AbstractCursorEvent } from './AbstractCursorEvent';
import { ICustomEvent } from '../../../shared/event';

export class MouseClickEvent extends AbstractCursorEvent implements ICustomEvent {
type = 'mouse:click';
}

export class MouseDoubleClickEvent extends AbstractCursorEvent implements ICustomEvent {
type = 'mouse:dblclick';
}
6 changes: 6 additions & 0 deletions src/app/core/events/cursor/MouseMoveEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { AbstractCursorEvent } from './AbstractCursorEvent';
import { ICustomEvent } from '../../../shared/event';

export class MouseMoveEvent extends AbstractCursorEvent implements ICustomEvent {
type = 'mouse:move';
}
5 changes: 5 additions & 0 deletions src/app/core/events/cursor/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './DragMoveEvent';
export * from './DragStartEvent';
export * from './DragStopEvent';
export * from './MouseClickEvent';
export * from './MouseMoveEvent';

0 comments on commit 04bc508

Please sign in to comment.