Render canvas connections overlay
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
Position,
|
||||
ReactFlow,
|
||||
ReactFlowProvider,
|
||||
ViewportPortal,
|
||||
useReactFlow,
|
||||
type Connection,
|
||||
type Edge,
|
||||
@@ -724,6 +725,84 @@ function clampViewport(viewport: FlowViewport, minZoom: number, maxZoom: number)
|
||||
};
|
||||
}
|
||||
|
||||
function buildConnectionPath(source: CanvasNode, target: CanvasNode) {
|
||||
const sourceX = source.x + source.width + 8;
|
||||
const sourceY = source.y + source.height / 2;
|
||||
const targetX = target.x - 8;
|
||||
const targetY = target.y + target.height / 2;
|
||||
const distance = Math.max(80, Math.abs(targetX - sourceX) * 0.45);
|
||||
return `M ${sourceX} ${sourceY} C ${sourceX + distance} ${sourceY}, ${targetX - distance} ${targetY}, ${targetX} ${targetY}`;
|
||||
}
|
||||
|
||||
function CanvasConnectionOverlay({
|
||||
nodes,
|
||||
connections,
|
||||
edgeStroke,
|
||||
edgeZIndex,
|
||||
}: {
|
||||
nodes: CanvasNode[];
|
||||
connections: CanvasConnection[];
|
||||
edgeStroke: string;
|
||||
edgeZIndex: number;
|
||||
}) {
|
||||
const nodeMap = useMemo(() => new Map(nodes.map(node => [node.id, node])), [nodes]);
|
||||
const visibleConnections = connections
|
||||
.map(connection => {
|
||||
const source = nodeMap.get(connection.sourceNodeId);
|
||||
const target = nodeMap.get(connection.targetNodeId);
|
||||
return source && target ? { connection, source, target } : null;
|
||||
})
|
||||
.filter((item): item is { connection: CanvasConnection; source: CanvasNode; target: CanvasNode } => !!item);
|
||||
|
||||
if (visibleConnections.length === 0) return null;
|
||||
|
||||
return (
|
||||
<ViewportPortal>
|
||||
<svg
|
||||
className="canvas-connection-overlay"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 1,
|
||||
height: 1,
|
||||
overflow: 'visible',
|
||||
pointerEvents: 'none',
|
||||
zIndex: edgeZIndex,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<defs>
|
||||
<marker
|
||||
id="canvas-connection-arrow"
|
||||
markerWidth="12"
|
||||
markerHeight="12"
|
||||
refX="10"
|
||||
refY="6"
|
||||
orient="auto"
|
||||
markerUnits="strokeWidth"
|
||||
>
|
||||
<path d="M 2 2 L 10 6 L 2 10 z" fill={edgeStroke} />
|
||||
</marker>
|
||||
</defs>
|
||||
{visibleConnections.map(({ connection, source, target }) => (
|
||||
<path
|
||||
key={connection.id}
|
||||
d={buildConnectionPath(source, target)}
|
||||
fill="none"
|
||||
stroke={edgeStroke}
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
markerEnd="url(#canvas-connection-arrow)"
|
||||
opacity={0.95}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
</ViewportPortal>
|
||||
);
|
||||
}
|
||||
|
||||
function FlowCanvasInner({
|
||||
nodes,
|
||||
connections,
|
||||
@@ -1020,6 +1099,12 @@ function FlowCanvasInner({
|
||||
>
|
||||
<Background gap={20} size={1.15} color={dotColor} />
|
||||
<Background gap={100} size={1.8} color={dotAccentColor} />
|
||||
<CanvasConnectionOverlay
|
||||
nodes={nodes}
|
||||
connections={connections}
|
||||
edgeStroke={edgeStroke}
|
||||
edgeZIndex={edgeZIndex}
|
||||
/>
|
||||
<style jsx global>{`
|
||||
.canvas-flow .react-flow__edges {
|
||||
z-index: ${edgeZIndex};
|
||||
|
||||
Reference in New Issue
Block a user