Skip to content

Example · Layout

Force-Directed Layout

Force-directed layouts simulate physical springs and charges so connected nodes attract and unconnected nodes repel. TopoKit's force layout uses Barnes-Hut for O(n log n) performance and converges quickly without manual tuning. The full configuration surface is below.

Minimal example

app.ts
import { create } from '@topokit/renderer-canvas';

const app = create(document.getElementById('graph')!, {
  nodes: [
    { id: 'a' }, { id: 'b' }, { id: 'c' }, { id: 'd' }, { id: 'e' }
  ],
  edges: [
    { id: '1', source: 'a', target: 'b' },
    { id: '2', source: 'b', target: 'c' },
    { id: '3', source: 'c', target: 'd' },
    { id: '4', source: 'd', target: 'e' },
    { id: '5', source: 'e', target: 'a' }
  ],
  layout: 'force',
  interactive: true,
});

Tunable options

app.ts
const app = create(container, {
  nodes, edges,
  layout: 'force',
  layoutOptions: {
    linkDistance: 120,        // preferred distance between connected nodes
    linkStrength: 0.6,        // 0..1, how strongly links pull
    chargeStrength: -300,     // negative = repulsion between all nodes
    centerStrength: 0.05,     // pull toward the canvas center
    collisionRadius: 28,     // minimum spacing between nodes
    theta: 0.9,               // Barnes-Hut approximation (lower = more accurate, slower)
    alpha: 1.0,               // initial simulation energy
    alphaDecay: 0.0228,       // how quickly the simulation cools
    iterations: 300,          // max iterations before stop
  },
});

Run layout in a Web Worker

For graphs over a few hundred nodes, run the simulation off-main-thread:

app.ts
import { workerLayoutRunner } from '@topokit/layouts/worker';

const app = create(container, {
  nodes, edges,
  layout: 'force',
  layoutRunner: workerLayoutRunner(),
});

See the Web Worker example for a complete walkthrough.