Files
goldenChart/frontend/src/utils/strategyEdgeInteraction.ts
T
2026-05-24 12:25:17 +09:00

72 lines
2.1 KiB
TypeScript

import {
getNodeDimensions,
pickSideFromPoint,
START_NODE_ID,
type HandleSide,
} from './strategyFlowLayout';
export type EdgeDragZone = 'source' | 'middle' | 'target';
/** 연결선 상 클릭/드래그 위치 → 좌(소스) / 중(경로) / 우(타겟) 구간 */
export function getEdgeDragZone(
sourceX: number,
sourceY: number,
targetX: number,
targetY: number,
pointerX: number,
pointerY: number,
): EdgeDragZone {
const dx = targetX - sourceX;
const dy = targetY - sourceY;
const len2 = dx * dx + dy * dy;
if (len2 < 4) return 'middle';
const t = ((pointerX - sourceX) * dx + (pointerY - sourceY) * dy) / len2;
const clamped = Math.max(0, Math.min(1, t));
if (clamped < 1 / 3) return 'source';
if (clamped > 2 / 3) return 'target';
return 'middle';
}
function sideToSourceHandle(side: HandleSide): string {
return `s-${side}`;
}
function sideToTargetHandle(side: HandleSide): string {
return `t-${side}`;
}
/** 드래그 위치에 맞는 소스(출발) 핸들 */
export function pickSourceHandleAtPoint(
nodeId: string,
flowPos: { x: number; y: number },
positions: Map<string, { x: number; y: number }>,
): string {
const pos = positions.get(nodeId) ?? { x: 0, y: 0 };
const dim = getNodeDimensions(nodeId);
return sideToSourceHandle(pickSideFromPoint(flowPos, pos, dim));
}
/** 드래그 위치에 맞는 타겟(도착) 핸들 */
export function pickTargetHandleAtPoint(
nodeId: string,
flowPos: { x: number; y: number },
positions: Map<string, { x: number; y: number }>,
): string {
const pos = positions.get(nodeId) ?? { x: 0, y: 0 };
const dim = getNodeDimensions(nodeId);
return sideToTargetHandle(pickSideFromPoint(flowPos, pos, dim));
}
export function buildPositionsFromNodes(
nodes: { id: string; position: { x: number; y: number } }[],
): Map<string, { x: number; y: number }> {
const map = new Map<string, { x: number; y: number }>();
for (const n of nodes) {
map.set(n.id, { x: n.position.x, y: n.position.y });
}
if (!map.has(START_NODE_ID)) {
map.set(START_NODE_ID, { x: 0, y: 220 });
}
return map;
}