Hi, this is part 2 of my LightDraw series. Last time we covered the big picture (dashboards, automotive, diagrams, UI). Today we go deep on one feature people keep asking about: diagram wire-flow animation, and how to drive every chart from plain JSON you can store, edit, or generate with AI.
By the end of this post you’ll be able to:
- Describe a flowchart, pipeline, network, org chart, schematic, or UML class diagram as JSON
- Pass that JSON to JavaScript and render it with LightDraw
- Turn on path animation (dashes + packets + status tint) and use the built-in play/pause toolbar
- Copy working examples without fighting a framework stack
Requires: lightdraw@1.2.1+ for the built-in diagram toolbar when flow.enabled is on.
The mental model (keep this)
Everything in this post follows the same three steps:
- Write a scene object:
{ type, props } - Mount it:
Diagram.fromJSON(type, props, app)→app.add(chart) - Optional polish:
fitToBounds, editor, flow controls
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/lightdraw@1/dist/lightdraw.min.css">
<div id="app" style="position:relative; width:800px; height:480px;"></div>
<script src="https://cdn.jsdelivr.net/npm/lightdraw@1/dist/lightdraw.min.js"></script>
<script>
const app = LightDraw.createApp('#app', {
width: 800,
height: 480,
renderer: 'canvas',
background: '#0f172a',
});
function mountDiagram(scene) {
app.clear();
const chart = LightDraw.Diagram.fromJSON(scene.type, scene.props, app);
app.add(chart);
LightDraw.Diagram.fitToBounds(chart, 800, 480, 24);
return chart;
}
// later: mountDiagram(yourScene);
</script>
That’s the whole contract. Your diagrams live as JSON. JS only loads and renders them.
1. Flowchart: decisions, paths, and motion
Figure: Flowchart with multi-path wire flow and status tint (idle → active → done).
A flowchart is nodes + edges. Animation is just an ordered list of node ids under flow.paths.
const flowchartScene = {
type: 'flowchart',
props: {
width: 800,
height: 480,
data: {
nodes: [
{ id: 'start', label: 'Start', type: 'start', x: 360, y: 24 },
{ id: 'check', label: 'Valid?', type: 'decision', x: 360, y: 110 },
{ id: 'process', label: 'Process', type: 'process', x: 360, y: 210 },
{ id: 'notify', label: 'Notify', type: 'process', x: 140, y: 210 },
{ id: 'end', label: 'Done', type: 'end', x: 360, y: 320 },
],
edges: [
{ from: 'start', to: 'check' },
{ from: 'check', to: 'process', label: 'Yes' },
{ from: 'check', to: 'notify', label: 'No' },
{ from: 'process', to: 'end' },
{ from: 'notify', to: 'end' },
],
},
flow: {
enabled: true,
mode: 'both', // 'dash' | 'packet' | 'both'
playback: 'loop', // or 'once'
highlight: 'pulse',
statusHighlight: true,
speed: 1.5,
pathGapMs: 400,
paths: [
['start', 'check', 'process', 'end'],
['start', 'check', 'notify', 'end'],
],
},
},
};
mountDiagram(flowchartScene);
Tip: Status tint needs packet or both. Grey = not yet visited, yellow = current hop, green = done for this path run.
2. Process pipeline: CI / ETL stages
Figure: Process pipeline stages animating in order.
const pipelineScene = {
type: 'processPipeline',
props: {
width: 800,
height: 280,
stages: [
{ id: 'ingest', label: 'Ingest', status: 'done', type: 'input' },
{ id: 'validate', label: 'Validate', status: 'done', type: 'test' },
{ id: 'build', label: 'Build', status: 'active', type: 'build' },
{ id: 'test', label: 'Test', status: 'pending', type: 'test' },
{ id: 'deploy', label: 'Deploy', status: 'pending', type: 'deploy' },
],
flow: {
enabled: true,
mode: 'both',
playback: 'loop',
statusHighlight: true,
path: ['ingest', 'validate', 'build', 'test', 'deploy'],
},
},
};
mountDiagram(pipelineScene);
Use a single path for one run, or paths: [['a','b'], ['a','c']] for alternating runs (same as flowchart).
3. Network topology: traffic between devices
Figure: Network icons with two traffic paths (edge → web, edge → API → DB).
const networkScene = {
type: 'networkTopology',
props: {
width: 800,
height: 400,
data: {
nodes: [
{ id: 'inet', label: 'Internet', type: 'cloud', x: 360, y: 24 },
{ id: 'fw', label: 'NGFW', type: 'ngfw', x: 360, y: 130 },
{ id: 'web', label: 'Web', type: 'server', x: 160, y: 260 },
{ id: 'api', label: 'API', type: 'server', x: 360, y: 260 },
{ id: 'db', label: 'SQL', type: 'sql_database', x: 560, y: 260 },
],
edges: [
{ from: 'inet', to: 'fw' },
{ from: 'fw', to: 'web' },
{ from: 'fw', to: 'api' },
{ from: 'api', to: 'db' },
],
},
flow: {
enabled: true,
mode: 'both',
playback: 'loop',
paths: [
['inet', 'fw', 'web'],
['inet', 'fw', 'api', 'db'],
],
},
},
};
mountDiagram(networkScene);
Node type values map to a Visio/Cisco-style catalog (server, router, ngfw, sql_database, cloud, …). Perfect for NOC boards and security runbooks.
4. Animation properties & controls (the JSON knobs)
Figure: Built-in toolbar (▶⏸↻ + zoom + Fit) with path status tint.
All of these live under props.flow and round-trip with Diagram.toJSON / fromJSON:
| Property | Values | What it does |
|---|---|---|
enabled | true / false | Start wire-flow animation |
mode | dash · packet · both | Marching dashes, traveling dot, or both |
playback | loop · once | Repeat forever, or play then pause |
paths / path | array of node ids | Ordered hops to animate |
speed | number (e.g. 1.5) | Playback rate |
pathGapMs | ms | Pause between path runs |
highlight | pulse · breathe · flash · none | Motion chrome on active hops |
statusHighlight | bool | Idle / active / done color tint |
statusColors | object | Override idle/active/done/error colors |
chrome | true (default) / false | Show ▶⏸↻ + zoom overlay |
Control from JS (same chart you mounted):
LightDraw.Diagram.applyFlow(app, chart, { /* same options as flow */ });
LightDraw.Diagram.pauseFlow(app, chart);
LightDraw.Diagram.resumeFlow(app, chart);
LightDraw.Diagram.toggleFlowPause(app, chart);
LightDraw.Diagram.replayFlow(app, chart);
LightDraw.Diagram.stopFlow(chart);
// Manual toolbar if you disabled chrome in JSON:
// LightDraw.Diagram.installToolbar(app, chart);
// LightDraw.Diagram.uninstallToolbar(chart);
Give the host #app { position: relative; } so the toolbar overlays correctly.
5. Org chart: hierarchy from a nested tree
Figure: Org chart rendered from a nested root JSON tree.
No edges array here, just a tree. Same mount helper.
const orgScene = {
type: 'orgChart',
props: {
width: 900,
height: 480,
root: {
name: 'Alex Rivera',
role: 'CEO',
children: [
{
name: 'Sam Chen',
role: 'CTO',
department: 'Engineering',
children: [
{ name: 'Priya N.', role: 'Platform Lead' },
{ name: 'Jordan K.', role: 'Frontend Lead' },
],
},
{
name: 'Morgan Lee',
role: 'CFO',
department: 'Finance',
children: [{ name: 'Riley P.', role: 'Controller' }],
},
{ name: 'Casey Brooks', role: 'COO', department: 'Ops' },
],
},
},
};
mountDiagram(orgScene);
// Optional: drag / resize / collapse in the editor
LightDraw.Diagram.installEditor(app, chart, {
mode: 'arrange',
allowResize: true,
});
6. Schematic diagram: IEC symbols as JSON
Figure: Battery → switch → resistor → LED → ground from a component list.
const schematicScene = {
type: 'electricalSchematic',
props: {
width: 800,
height: 360,
components: [
{ id: 'bat', type: 'battery', x: 80, y: 120, label: 'BAT' },
{ id: 'sw', type: 'spst', x: 220, y: 120, label: 'S1' },
{ id: 'r1', type: 'resistor', x: 360, y: 120, label: 'R1' },
{ id: 'led', type: 'led', x: 500, y: 120, label: 'D1' },
{ id: 'gnd', type: 'ground', x: 500, y: 220, label: 'GND' },
],
},
};
mountDiagram(schematicScene);
Symbol kinds come from the IEC catalog (spst, nmos, opAmp, led, …). Discover them with LightDraw.Diagram.listSchematicSymbols().
7. UML class diagram: structure + animated relations
Figure: Class boxes with inheritance paths animated for a walkthrough.
const umlScene = {
type: 'classDiagram',
props: {
width: 800,
height: 400,
data: {
classes: [
{ id: 'drawable', name: 'Drawable', x: 80, y: 40, methods: ['draw()'], stereotype: 'interface' },
{ id: 'shape', name: 'Shape', x: 360, y: 40, attrs: ['id: string'], methods: ['draw()'] },
{ id: 'rect', name: 'Rect', x: 220, y: 240, attrs: ['w', 'h'], methods: ['draw()'] },
{ id: 'circle', name: 'Circle', x: 520, y: 240, attrs: ['r'], methods: ['draw()'] },
],
relations: [
{ from: 'shape', to: 'drawable', type: 'realization' },
{ from: 'rect', to: 'shape', type: 'inheritance' },
{ from: 'circle', to: 'shape', type: 'inheritance' },
],
},
flow: {
enabled: true,
mode: 'both',
playback: 'loop',
paths: [
['rect', 'shape', 'drawable'],
['circle', 'shape', 'drawable'],
],
},
},
};
mountDiagram(umlScene);
Load JSON from a file or API
Because the scene is just data, you can keep charts next to configs:
// From a static file
const scene = await fetch('/scenes/onboarding-flow.json').then((r) => r.json());
mountDiagram(scene);
// Or via the app helper when the diagram plugin is registered
app.loadJSON(scene);
// Round-trip after the user edits in the canvas
const saved = LightDraw.Diagram.toJSON(chart);
localStorage.setItem('my-diagram', JSON.stringify(saved));
This is why LightDraw works well for AI agents and config-driven UIs: the agent emits JSON; your page only mounts it.
Quick reference: diagram type values
type | Key props | Wire flow? |
|---|---|---|
flowchart | data.nodes, data.edges | Yes |
stateMachine | data.states, data.transitions | Yes |
processPipeline | stages[] | Yes |
networkTopology | data.nodes, data.edges | Yes |
canNetwork | data.ecus, data.busLabel | Yes (virtual bus hops) |
classDiagram | data.classes, data.relations | Yes |
orgChart | root tree | No |
electricalSchematic | components[] | No |
mindMap | center, branches | No |
Try it yourself
npm install lightdrawor drop the CDN script from the top of this post- Copy any scene JSON above into
mountDiagram(scene) - Open the live diagram playground: rakeshrajena.github.io/lightDraw/#diagram
- Read the flow guide: docs/diagram-flow.md
If this helped, tell me which diagram type you want next (CAN bus walkthrough, mind maps, or exporting animated scenes for docs). Part 1 introduced the library; this part should be enough to ship a real animated diagram from JSON alone.
LightDraw · zero-dependency · JSON-first graphics for the browser
















