mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2026-03-05 15:05:27 +00:00
fix: optimize canvas mouse interactions
This commit is contained in:
@@ -105,6 +105,9 @@ type DistributeType = 'horizontal' | 'vertical';
|
|||||||
const MOVE_STEP = 2;
|
const MOVE_STEP = 2;
|
||||||
const MOVE_STEP_LARGE = 10;
|
const MOVE_STEP_LARGE = 10;
|
||||||
const COPY_TRANSLATION = 40;
|
const COPY_TRANSLATION = 40;
|
||||||
|
const RIGHT_MOUSE_BUTTON = 2;
|
||||||
|
const RIGHT_DRAG_THRESHOLD = 2;
|
||||||
|
const RIGHT_DRAG_CONTEXTMENU_SUPPRESS_MS = 300;
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
height?: string;
|
height?: string;
|
||||||
@@ -141,6 +144,12 @@ let nextPasteDistance = COPY_TRANSLATION;
|
|||||||
let containerResizeObserver: ResizeObserver | null = null;
|
let containerResizeObserver: ResizeObserver | null = null;
|
||||||
let groupRuleValidationTimer: ReturnType<typeof setTimeout> | null = null;
|
let groupRuleValidationTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
let unsubscribeSharedGroupRules: (() => void) | null = null;
|
let unsubscribeSharedGroupRules: (() => void) | null = null;
|
||||||
|
let isRightDragging = false;
|
||||||
|
let rightDragMoved = false;
|
||||||
|
let rightDragLastX = 0;
|
||||||
|
let rightDragLastY = 0;
|
||||||
|
let rightDragDistance = 0;
|
||||||
|
let suppressContextMenuUntil = 0;
|
||||||
|
|
||||||
const resolveResizeHost = () => {
|
const resolveResizeHost = () => {
|
||||||
const container = containerRef.value;
|
const container = containerRef.value;
|
||||||
@@ -166,6 +175,71 @@ const handleWindowResize = () => {
|
|||||||
resizeCanvas();
|
resizeCanvas();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function handleRightDragMouseMove(event: MouseEvent) {
|
||||||
|
if (!isRightDragging) return;
|
||||||
|
|
||||||
|
const deltaX = event.clientX - rightDragLastX;
|
||||||
|
const deltaY = event.clientY - rightDragLastY;
|
||||||
|
rightDragLastX = event.clientX;
|
||||||
|
rightDragLastY = event.clientY;
|
||||||
|
|
||||||
|
if (deltaX === 0 && deltaY === 0) return;
|
||||||
|
|
||||||
|
rightDragDistance += Math.abs(deltaX) + Math.abs(deltaY);
|
||||||
|
if (!rightDragMoved && rightDragDistance >= RIGHT_DRAG_THRESHOLD) {
|
||||||
|
rightDragMoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightDragMoved) {
|
||||||
|
lf.value?.translate(deltaX, deltaY);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopRightDrag() {
|
||||||
|
if (!isRightDragging) return;
|
||||||
|
|
||||||
|
isRightDragging = false;
|
||||||
|
flowHostRef.value?.classList.remove('flow-container--panning');
|
||||||
|
window.removeEventListener('mousemove', handleRightDragMouseMove);
|
||||||
|
window.removeEventListener('mouseup', handleRightDragMouseUp);
|
||||||
|
|
||||||
|
if (rightDragMoved) {
|
||||||
|
suppressContextMenuUntil = Date.now() + RIGHT_DRAG_CONTEXTMENU_SUPPRESS_MS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRightDragMouseUp() {
|
||||||
|
stopRightDrag();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCanvasMouseDown(event: MouseEvent) {
|
||||||
|
if (event.button !== RIGHT_MOUSE_BUTTON) return;
|
||||||
|
|
||||||
|
const target = event.target as HTMLElement | null;
|
||||||
|
if (target?.closest('.lf-menu')) return;
|
||||||
|
if (!containerRef.value?.contains(target)) return;
|
||||||
|
|
||||||
|
isRightDragging = true;
|
||||||
|
rightDragMoved = false;
|
||||||
|
rightDragDistance = 0;
|
||||||
|
rightDragLastX = event.clientX;
|
||||||
|
rightDragLastY = event.clientY;
|
||||||
|
suppressContextMenuUntil = 0;
|
||||||
|
|
||||||
|
flowHostRef.value?.classList.add('flow-container--panning');
|
||||||
|
window.addEventListener('mousemove', handleRightDragMouseMove);
|
||||||
|
window.addEventListener('mouseup', handleRightDragMouseUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCanvasContextMenu(event: MouseEvent) {
|
||||||
|
if (Date.now() >= suppressContextMenuUntil) return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
suppressContextMenuUntil = 0;
|
||||||
|
}
|
||||||
|
|
||||||
function isInputLike(event?: KeyboardEvent) {
|
function isInputLike(event?: KeyboardEvent) {
|
||||||
const target = event?.target as HTMLElement | null;
|
const target = event?.target as HTMLElement | null;
|
||||||
if (!target) return false;
|
if (!target) return false;
|
||||||
@@ -757,6 +831,7 @@ onMounted(() => {
|
|||||||
lf.value = new LogicFlow({
|
lf.value = new LogicFlow({
|
||||||
container: containerRef.value,
|
container: containerRef.value,
|
||||||
grid: { type: 'dot', size: 10 },
|
grid: { type: 'dot', size: 10 },
|
||||||
|
stopMoveGraph: true,
|
||||||
allowResize: true,
|
allowResize: true,
|
||||||
allowRotate: true,
|
allowRotate: true,
|
||||||
overlapMode: -1,
|
overlapMode: -1,
|
||||||
@@ -998,6 +1073,9 @@ onMounted(() => {
|
|||||||
|
|
||||||
registerNodes(lfInstance);
|
registerNodes(lfInstance);
|
||||||
setLogicFlowInstance(lfInstance);
|
setLogicFlowInstance(lfInstance);
|
||||||
|
applySelectionSelect(selectionEnabled.value);
|
||||||
|
containerRef.value?.addEventListener('mousedown', handleCanvasMouseDown);
|
||||||
|
containerRef.value?.addEventListener('contextmenu', handleCanvasContextMenu, true);
|
||||||
|
|
||||||
// 监听所有可能的节点添加事件
|
// 监听所有可能的节点添加事件
|
||||||
lfInstance.on(EventType.NODE_ADD, ({ data }) => {
|
lfInstance.on(EventType.NODE_ADD, ({ data }) => {
|
||||||
@@ -1025,6 +1103,7 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
lfInstance.on(EventType.GRAPH_RENDERED, () => {
|
lfInstance.on(EventType.GRAPH_RENDERED, () => {
|
||||||
|
applySelectionSelect(selectionEnabled.value);
|
||||||
normalizeAllNodes();
|
normalizeAllNodes();
|
||||||
scheduleGroupRuleValidation(0);
|
scheduleGroupRuleValidation(0);
|
||||||
});
|
});
|
||||||
@@ -1129,6 +1208,9 @@ onBeforeUnmount(() => {
|
|||||||
}
|
}
|
||||||
unsubscribeSharedGroupRules?.();
|
unsubscribeSharedGroupRules?.();
|
||||||
unsubscribeSharedGroupRules = null;
|
unsubscribeSharedGroupRules = null;
|
||||||
|
containerRef.value?.removeEventListener('mousedown', handleCanvasMouseDown);
|
||||||
|
containerRef.value?.removeEventListener('contextmenu', handleCanvasContextMenu, true);
|
||||||
|
stopRightDrag();
|
||||||
lf.value?.destroy();
|
lf.value?.destroy();
|
||||||
lf.value = null;
|
lf.value = null;
|
||||||
destroyLogicFlowInstance();
|
destroyLogicFlowInstance();
|
||||||
@@ -1154,6 +1236,9 @@ onBeforeUnmount(() => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
.flow-container--panning :deep(.lf-canvas-overlay) {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
.container {
|
.container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user