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

Elkjs Tree

Like our dagre example, this example shows how you can integrate elkjs  with Svelte Flow for more advanced tree layouts. The code for this example builds a similar tree to the dagre example, but you can look at the reference here  to see what you can configure (hint: it’s a lot).

<script lang="ts"> import { writable } from 'svelte/store'; import ELK from 'elkjs/lib/elk.bundled.js'; import { SvelteFlow, Background, Position, ConnectionLineType, Panel, useSvelteFlow, type Node, type Edge } from '@xyflow/svelte'; import '@xyflow/svelte/dist/style.css'; import { initialNodes, initialEdges } from './nodes-and-edges'; import { onMount } from 'svelte'; const nodes = writable<Node[]>([]); const edges = writable<Edge[]>([]); const { fitView } = useSvelteFlow(); const elk = new ELK(); // Elk has a *huge* amount of options to configure. To see everything you can // tweak check out: // // - https://www.eclipse.org/elk/reference/algorithms.html // - https://www.eclipse.org/elk/reference/options.html const elkOptions = { 'elk.algorithm': 'layered', 'elk.layered.spacing.nodeNodeBetweenLayers': '100', 'elk.spacing.nodeNode': '80' }; function getLayoutedElements(nodes: Node[], edges: Edge[], options = {}) { const isHorizontal = options?.['elk.direction'] === 'RIGHT'; const graph = { id: 'root', layoutOptions: options, children: nodes.map((node) => ({ ...node, // Adjust the target and source handle positions based on the layout // direction. targetPosition: isHorizontal ? Position.Left : Position.Top, sourcePosition: isHorizontal ? Position.Right : Position.Bottom, // Hardcode a width and height for elk to use when layouting. width: 150, height: 50 })), edges: edges }; return elk .layout(graph) .then((layoutedGraph) => ({ nodes: layoutedGraph.children.map((node) => ({ ...node, // React Flow expects a position property on the node instead of `x` // and `y` fields. position: { x: node.x, y: node.y } })), edges: layoutedGraph.edges })) .catch(console.error); } function onLayout(direction: string, useInitialNodes = false) { const opts = { 'elk.direction': direction, ...elkOptions }; const ns = useInitialNodes ? initialNodes : $nodes; const es = useInitialNodes ? initialEdges : $edges; getLayoutedElements(ns, es, opts).then(({ nodes: layoutedNodes, edges: layoutedEdges }) => { $nodes = layoutedNodes; $edges = layoutedEdges; fitView(); window.requestAnimationFrame(() => fitView()); }); } onMount(() => { onLayout('DOWN', true); }); </script> <div style="height:100vh;"> <SvelteFlow {nodes} {edges} fitView connectionLineType={ConnectionLineType.SmoothStep} defaultEdgeOptions={{ type: 'smoothstep', animated: true }} > <Panel position="top-right"> <button on:click={() => onLayout('DOWN')}>vertical layout</button> <button on:click={() => onLayout('RIGHT')}>horizontal layout</button> </Panel> <Background /> </SvelteFlow> </div>
Last updated on