Skip to Content
ExamplesEdges

Edge Intersection

This example shows how you can detect an intersection between a dragged node and an edge.

The default interactionWidth of the edges is set to 75 via the defaultEdgeOptions. We set a wider interaction area so that we can easily find the edge and node intersections.

import React, { useCallback, useRef } from 'react'; import { Background, Controls, ReactFlow, addEdge, useNodesState, useEdgesState, type OnConnect, type OnNodeDrag, useReactFlow, type Node, type Edge, type DefaultEdgeOptions, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; const defaultEdgeOptions: DefaultEdgeOptions = { interactionWidth: 75, }; const initialNodes: Node[] = [ { id: 'a', type: 'input', position: { x: 200, y: 0 }, data: { label: 'Node A' }, }, { id: 'b', position: { x: 0, y: 200 }, data: { label: 'Node B' }, }, { id: 'c', position: { x: 0, y: 0 }, data: { label: 'Node C' } }, ]; const initialEdges: Edge[] = [{ id: 'a->b', source: 'a', target: 'b' }]; export default function App() { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const onConnect: OnConnect = useCallback( (connection) => setEdges((edges) => addEdge(connection, edges)), [setEdges], ); const { updateEdge, getEdge, addEdges } = useReactFlow(); const overlappedEdgeRef = useRef<string | null>(null); const onNodeDragStop: OnNodeDrag = useCallback( (event, node) => { const edgeId = overlappedEdgeRef.current; if (!edgeId) return; const edge = getEdge(edgeId); if (!edge) return; updateEdge(edgeId, { source: edge.source, target: node.id, style: {} }); addEdges({ id: `${node.id}->${edge.target}`, source: node.id, target: edge.target, }); overlappedEdgeRef.current = null; }, [getEdge, addEdges, updateEdge], ); const onNodeDrag: OnNodeDrag = useCallback( (e, node) => { const nodeDiv = document.querySelector( `.react-flow__node[data-id=${node.id}]`, ); if (!nodeDiv) return; const rect = nodeDiv.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const edgeFound = document .elementsFromPoint(centerX, centerY) .find((el) => el.classList.contains('react-flow__edge-interaction'), )?.parentElement; const edgeId = edgeFound?.dataset.id; if (edgeId) updateEdge(edgeId, { style: { stroke: 'black' } }); else if (overlappedEdgeRef.current) updateEdge(overlappedEdgeRef.current, { style: {} }); overlappedEdgeRef.current = edgeId || null; }, [updateEdge], ); return ( <ReactFlow nodes={nodes} onNodesChange={onNodesChange} edges={edges} onEdgesChange={onEdgesChange} onConnect={onConnect} onNodeDragStop={onNodeDragStop} onNodeDrag={onNodeDrag} defaultEdgeOptions={defaultEdgeOptions} fitView > <Background /> <Controls /> </ReactFlow> ); }
Last updated on