Skip to Content
📣 We just released Svelte Flow 1.0 Alpha — try it out and give us your feedback!
ExamplesNodesProximity Connect

Proximity Connect

This example shows how to automatically create edges when a node is dropped in close proximity to another one. While dragging, a dotted connection line is displayed to show which edge will be created if you drop the node.

<script lang="ts"> import { writable } from 'svelte/store'; import { SvelteFlow, Background, type Node, type Edge } from '@xyflow/svelte'; import '@xyflow/svelte/dist/style.css'; import { initialNodes, initialEdges } from './nodes-and-edges'; const nodes = writable<Node[]>(initialNodes); const edges = writable<Edge[]>(initialEdges); const MIN_DISTANCE = 150; function getClosestEdge(node: Node, nodes: Node[]) { const closestNode = nodes.reduce( (res, n) => { if (n.id !== node.id) { const dx = n.position.x - node.position.x; const dy = n.position.y - node.position.y; const d = Math.sqrt(dx * dx + dy * dy); if (d < res.distance && d < MIN_DISTANCE) { res.distance = d; res.node = n; } } return res; }, <{ distance: number; node: Node | null }>{ distance: Number.MAX_VALUE, node: null } ); if (!closestNode.node) { return null; } const closeNodeIsSource = closestNode.node.position.x < node.position.x; return { id: closeNodeIsSource ? `${node.id}-${closestNode.node.id}` : `${closestNode.node.id}-${node.id}`, source: closeNodeIsSource ? closestNode.node.id : node.id, target: closeNodeIsSource ? node.id : closestNode.node.id, class: 'temp' }; } function onNodeDrag({ detail: { targetNode: node } }) { const closestEdge = getClosestEdge(node, $nodes); let edgeAlreadyExists = false; $edges.forEach((edge, i) => { if (edgeAlreadyExists) { return; } if (closestEdge) { // non-temporary edge already exists if (edge.source === closestEdge.source && edge.target === closestEdge.target) { edgeAlreadyExists = true; return; } if (edge.class !== 'temp') { return; } if (edge.source !== closestEdge.source || edge.target !== closestEdge.target) { $edges[i] = closestEdge; // replace the edge edgeAlreadyExists = true; } } else if (edge.class === 'temp') { $edges.splice(i, 1); // remove edge } }); if (closestEdge && !edgeAlreadyExists) { $edges.push(closestEdge); } $edges = $edges; } function onNodeDragStop() { $edges.forEach((edge) => { if (edge.class === 'temp') { edge.class = ''; } }); $edges = $edges; } </script> <div style="height:100vh;"> <SvelteFlow {nodes} {edges} fitView on:nodedrag={onNodeDrag} on:nodedragstop={onNodeDragStop}> <Background /> </SvelteFlow> </div> <style> :global(.svelte-flow .svelte-flow__edge-path) { stroke: #333; stroke-width: 2; } :global(.svelte-flow .temp .svelte-flow__edge-path) { stroke: #bbb; stroke-dasharray: 5 5; } :global(.svelte-flow .svelte-flow__node) { border-radius: 100%; background-color: #fff; width: 50px; height: 50px; display: flex; align-items: center; justify-content: center; } </style>
Last updated on