Layout Engine
The Layout Engine provides automatic arrangement algorithms for organizing diagram elements.
Applying Layouts
// Apply layout to all items with ports
await app.diagramSystem.applyLayout(null, 'hierarchical', {
direction: 'TB',
levelSpacing: 100,
nodeSpacing: 80
});
// Apply to specific items
await app.diagramSystem.applyLayout([item1, item2, item3], 'grid', {
columns: 3
});
Layout Types
Hierarchical
Arranges items in levels based on connection hierarchy. Best for flowcharts and org charts.
await app.diagramSystem.applyLayout(items, 'hierarchical', {
direction: 'TB', // 'TB', 'BT', 'LR', 'RL'
levelSpacing: 100, // Space between levels
nodeSpacing: 80, // Space between siblings
padding: 50 // Canvas padding
});
Directions:
| Direction | Description |
|---|---|
TB |
Top to Bottom |
BT |
Bottom to Top |
LR |
Left to Right |
RL |
Right to Left |
// Top-down flowchart
await app.diagramSystem.applyLayout(items, 'hierarchical', {
direction: 'TB'
});
// Left-to-right org chart
await app.diagramSystem.applyLayout(items, 'hierarchical', {
direction: 'LR'
});
Force-Directed
Physics-based layout where connected nodes attract and unconnected nodes repel. Best for network diagrams and relationship graphs.
await app.diagramSystem.applyLayout(items, 'force-directed', {
iterations: 100, // Simulation steps
repulsion: 5000, // Node repulsion force
attraction: 0.1, // Edge attraction force
damping: 0.9 // Velocity damping
});
Parameters:
| Parameter | Default | Description |
|---|---|---|
iterations |
100 | Number of simulation steps |
repulsion |
5000 | Force pushing nodes apart |
attraction |
0.1 | Force pulling connected nodes |
damping |
0.9 | Velocity reduction per step |
Tree
Dendrogram-style layout for hierarchical tree structures.
await app.diagramSystem.applyLayout(items, 'tree', {
direction: 'TB', // Layout direction
levelSpacing: 100, // Vertical/horizontal gap between levels
nodeSpacing: 80, // Gap between siblings
padding: 50
});
Radial
Concentric circle layout with root nodes at center.
await app.diagramSystem.applyLayout(items, 'radial', {
levelSpacing: 80, // Radius increment per level
padding: 50
});
Grid
Simple grid arrangement, useful for uniform positioning.
await app.diagramSystem.applyLayout(items, 'grid', {
columns: 4, // Auto-calculated if not set
nodeSpacing: 80, // Cell spacing
padding: 50
});
Animation
Layouts can animate smoothly or apply instantly:
// Animated layout (default)
await app.diagramSystem.applyLayout(items, 'hierarchical', {
animate: true,
animationDuration: 300 // Milliseconds
});
// Instant layout
await app.diagramSystem.applyLayout(items, 'hierarchical', {
animate: false
});
Layout Settings
Update default layout settings:
app.diagramSystem.layoutEngine.updateSettings({
direction: 'LR',
levelSpacing: 120,
nodeSpacing: 100,
padding: 60,
animate: true,
animationDuration: 400
});
Graph Analysis
The layout engine builds a graph from connectors:
// Build adjacency graph (internal method)
const graph = app.diagramSystem.layoutEngine.buildGraph(items);
// Returns: Map<item, connectedItems[]>
// Find root nodes (no incoming edges)
const roots = app.diagramSystem.layoutEngine.findRoots(graph, items);
// Assign levels via BFS
const levels = app.diagramSystem.layoutEngine.assignLevels(graph, roots);
// Returns: Map<item, levelNumber>
Canvas Bounds
Layouts automatically consider canvas size:
- Items stay within canvas bounds with padding
- Grid layout calculates optimal column count
- Radial layout limits radius to fit
- Hierarchical layout centers and scales if needed
Connector Updates
After layout, connectors are automatically refreshed:
// Layout moves items
await app.diagramSystem.applyLayout(items, 'hierarchical');
// Connectors automatically update their paths
Examples
Flowchart Layout
// Create flowchart shapes
const start = app.diagramSystem.createShape('terminal', { label: 'Start' });
const step1 = app.diagramSystem.createShape('process', { label: 'Step 1' });
const step2 = app.diagramSystem.createShape('process', { label: 'Step 2' });
const decision = app.diagramSystem.createShape('decision', { label: 'Check' });
const end = app.diagramSystem.createShape('terminal', { label: 'End' });
// Connect them
app.diagramSystem.connect(start, step1);
app.diagramSystem.connect(step1, step2);
app.diagramSystem.connect(step2, decision);
app.diagramSystem.connect(decision, end);
// Apply hierarchical layout
await app.diagramSystem.applyLayout(null, 'hierarchical', {
direction: 'TB',
levelSpacing: 100
});
Network Diagram
// Create network nodes
const cloud = app.diagramSystem.createShape('cloud', { label: 'Internet' });
const router = app.diagramSystem.createShape('server', { label: 'Router' });
const server1 = app.diagramSystem.createShape('server', { label: 'Web' });
const server2 = app.diagramSystem.createShape('server', { label: 'DB' });
const server3 = app.diagramSystem.createShape('server', { label: 'App' });
// Connect
app.diagramSystem.connect(cloud, router);
app.diagramSystem.connect(router, server1);
app.diagramSystem.connect(router, server2);
app.diagramSystem.connect(router, server3);
app.diagramSystem.connect(server1, server2);
app.diagramSystem.connect(server1, server3);
// Force-directed for natural spacing
await app.diagramSystem.applyLayout(null, 'force-directed', {
iterations: 150,
repulsion: 8000
});
Radial Org Chart
// Create org chart
const ceo = app.diagramSystem.createShape('process', { label: 'CEO' });
const vp1 = app.diagramSystem.createShape('process', { label: 'VP Sales' });
const vp2 = app.diagramSystem.createShape('process', { label: 'VP Eng' });
const vp3 = app.diagramSystem.createShape('process', { label: 'VP Ops' });
// ... more nodes
// Connect hierarchy
app.diagramSystem.connect(ceo, vp1);
app.diagramSystem.connect(ceo, vp2);
app.diagramSystem.connect(ceo, vp3);
// Radial layout places CEO at center
await app.diagramSystem.applyLayout(null, 'radial', {
levelSpacing: 120
});
Grid Gallery
// Create items without connections
const items = [];
for (let i = 0; i < 12; i++) {
items.push(app.diagramSystem.createShape('rectangle', {
label: `Item ${i + 1}`
}));
}
// Grid layout with 4 columns
await app.diagramSystem.applyLayout(items, 'grid', {
columns: 4,
nodeSpacing: 100
});
Performance
| Layout Type | Complexity | Best For |
|---|---|---|
| Grid | O(n) | Any size |
| Hierarchical | O(n log n) | < 200 nodes |
| Tree | O(n log n) | < 200 nodes |
| Radial | O(n log n) | < 100 nodes |
| Force-Directed | O(n²) per iteration | < 50 nodes |
For large diagrams (100+ nodes), use hierarchical or grid layouts for best performance.