The Challenge of Edge Connections
In an AI workflow editor, edges (connections between nodes) are a core interaction. To let users connect nodes intuitively, I implemented port snapping, Bezier path rendering, and type validation.
Bezier Path Calculation
flowchart LR
A["출발점 (x1,y1)"] --> B["제어점1 (cx1,cy1)"]
B --> C["제어점2 (cx2,cy2)"]
C --> D["도착점 (x2,y2)"]
function calcBezierPath(
source: Point, target: Point
): string {
const dx = Math.abs(target.x - source.x);
const controlOffset = Math.max(50, dx * 0.4);
return `M ${source.x} ${source.y}
C ${source.x + controlOffset} ${source.y},
${target.x - controlOffset} ${target.y},
${target.x} ${target.y}`;
}
Port Position Calculation and Zoom Level
Without accounting for the zoom level, port positions will be misaligned from their actual locations:
// 6/12 커밋: 줌 레벨을 고려한 포트 좌표 계산
function getPortWorldPosition(portElement: HTMLElement, zoom: number) {
const rect = portElement.getBoundingClientRect();
const canvasRect = canvasRef.current.getBoundingClientRect();
return {
x: (rect.left - canvasRect.left + rect.width / 2) / zoom,
y: (rect.top - canvasRect.top + rect.height / 2) / zoom
};
}
Snap Algorithm
flowchart TD
A[마우스 이동] --> B[가까운 포트 탐색]
B --> C{거리 < 임계값?}
C -->|Yes| D{타입 호환?}
C -->|No| E[일반 미리보기]
D -->|호환| F[스냅 미리보기]
D -->|비호환| G[스냅 해제 + 미리보기 초기화]
F --> H[마우스 업 시 연결 확정]
Preventing Duplicate Edges
A bug that allowed duplicate edges on the same port pair was fixed on 6/13:
function canAddEdge(source: string, target: string): boolean {
return !edges.some(
e => e.source === source && e.target === target
);
}
Edge Re-wiring Logic
Functionality to detach an existing edge and reconnect it to a different port (6/13):
function handlePortMouseDown(portId: string) {
// 이미 연결된 엣지가 있으면 분리
const existingEdge = edges.find(e => e.target === portId);
if (existingEdge) {
removeEdge(existingEdge.id);
startEdgeFrom(existingEdge.source);
} else {
startEdgeFrom(portId);
}
}
These features were implemented across a total of 12 commits (6/11–6/18).