D3 Graphs
Documentation for Developers
🎨 D3.js Interactive Graphs System
Complete guide to creating and using D3.js diagrams in our documentation system
🔍 How It Works - The Magic Behind the Scenes
When you add a simple code block like this:
full
Here's exactly what happens:
1. 📖 Markdown Parsing
// In enhanced-markdown-renderer.component.ts
if (language === 'd3-architecture' || language === 'd3-nx') {
const preset = content.includes('simplified') ? 'simplified' : 'full';
return {
element: {
type: 'd3-architecture',
d3Config: { preset, width: 1200, height: 800 }
}
};
}
2. 🎯 Component Selection
<!-- The renderer detects 'd3-architecture' type and renders: -->
<app-d3-architecture-diagram
[data]="getD3DiagramData('full')"
[title]="'Complete NX Architecture'"
[width]="1200"
[height]="800">
</app-d3-architecture-diagram>
3. 📊 Data Loading
// From nx-architecture.data.ts
export const NX_ARCHITECTURE_DATA = {
nodes: [
{ id: 'core-types', name: 'core-types', layer: 'foundation' },
{ id: 'ux-framework', name: 'ux-framework', layer: 'framework' },
// ... 16 total libraries
],
links: [
{ source: 'core-types', target: 'ux-framework' },
{ source: 'shared-ui', target: 'widgets' },
// ... actual dependency relationships
]
};
4. 🎨 D3 Rendering
// D3 creates the interactive visualization
const simulation = d3.forceSimulation(nodes)
.force('link', d3.forceLink(links))
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter())
.force('collision', d3.forceCollide());
🚀 Usage Guide
Basic Syntax
Full Architecture Diagram
full
Simplified Overview
simplified
Custom Configuration
full
Available Presets
| Preset | Description | Nodes | Use Case |
|---|---|---|---|
full |
Complete architecture | 16 libraries | Detailed technical documentation |
simplified |
High-level overview | 4 layer groups | Executive summaries, presentations |
🛠 Creating New D3 Diagrams
Step 1: Define Your Data Structure
Create a new data file (e.g., my-diagram.data.ts):
export interface MyNode {
id: string;
name: string;
category: 'backend' | 'frontend' | 'database';
size?: number;
}
export interface MyLink {
source: string;
target: string;
strength?: number;
}
export const MY_DIAGRAM_DATA = {
nodes: [
{ id: 'api', name: 'REST API', category: 'backend' },
{ id: 'web', name: 'Web App', category: 'frontend' },
{ id: 'db', name: 'Database', category: 'database' }
],
links: [
{ source: 'web', target: 'api' },
{ source: 'api', target: 'db' }
]
};
Step 2: Create a D3 Component
@Component({
selector: 'app-my-diagram',
standalone: true,
template: `
<div class="diagram-container">
<svg [attr.width]="width()" [attr.height]="height()"></svg>
</div>
`
})
export class MyDiagramComponent {
data = input.required<MyDiagramData>();
width = input<number>(800);
height = input<number>(600);
// D3 rendering logic here...
}
Step 3: Register in Markdown Renderer
Add to enhanced-markdown-renderer.component.ts:
// In parseCodeBlock method
if (language === 'my-diagram') {
return {
element: { type: 'my-diagram', content, title }
};
}
// In template
@case ('my-diagram') {
<app-my-diagram [data]="getMyDiagramData()"></app-my-diagram>
}
Step 4: Use in Markdown
preset-name
🎨 Advanced Styling Techniques
Layer-Based Color Coding
private getLayerColor(layer: string): string {
const colors = {
foundation: '#4F46E5', // Indigo
framework: '#059669', // Emerald
feature: '#DC2626', // Red
application: '#7C3AED' // Violet
};
return colors[layer];
}
Interactive Hover Effects
nodeGroups
.on('mouseover', (event, d) => {
// Highlight connected nodes
this.highlightConnections(d.id);
})
.on('mouseout', () => {
// Reset all styles
this.resetHighlighting();
});
Force Simulation Configuration
const simulation = d3.forceSimulation(nodes)
.force('link', d3.forceLink(links)
.distance(120) // Distance between connected nodes
.strength(0.7)) // Link strength
.force('charge', d3.forceManyBody()
.strength(-1000)) // Repulsion between nodes
.force('center', d3.forceCenter(width/2, height/2))
.force('collision', d3.forceCollide()
.radius(55)); // Prevent overlap
🎯 Best Practices
✅ DO:
- Use meaningful node IDs that match your data
- Implement proper TypeScript interfaces
- Add hover states for interactivity
- Use consistent color schemes
- Make diagrams responsive
- Add proper ARIA labels for accessibility
❌ DON'T:
- Hardcode colors in templates
- Create overlapping nodes without collision detection
- Forget to handle edge cases (empty data, missing links)
- Make diagrams too small to read
- Skip proper error handling
🔧 Troubleshooting
Common Issues:
"Diagram not rendering"
- Check browser console for errors
- Verify data structure matches interfaces
- Ensure component is properly imported
"Nodes overlapping"
// Increase collision radius
.force('collision', d3.forceCollide().radius(60))
"Text not visible"
// Ensure proper text styling
.style('fill', '#ffffff')
.style('font-size', '14px')
.style('pointer-events', 'none')
"Links not connecting"
- Verify source/target IDs match node IDs exactly
- Check that links array is properly formatted
📊 Performance Optimization
For Large Datasets (100+ nodes):
// Limit simulation iterations
simulation.alphaDecay(0.05);
// Use canvas instead of SVG for better performance
const canvas = d3.select(container).append('canvas');
// Implement viewport culling
const visibleNodes = nodes.filter(n => isInViewport(n));
Memory Management:
ngOnDestroy() {
// Stop simulation
this.simulation?.stop();
// Clear event listeners
this.svg?.selectAll('*').on('.drag', null);
}
🎪 Examples & Templates
Network Topology Diagram
const networkData = {
nodes: [
{ id: 'router', name: 'Router', type: 'network' },
{ id: 'server1', name: 'Web Server', type: 'server' },
{ id: 'db', name: 'Database', type: 'storage' }
],
links: [
{ source: 'router', target: 'server1' },
{ source: 'server1', target: 'db' }
]
};
Organizational Chart
const orgData = {
nodes: [
{ id: 'ceo', name: 'CEO', level: 1 },
{ id: 'cto', name: 'CTO', level: 2 },
{ id: 'dev1', name: 'Developer', level: 3 }
],
links: [
{ source: 'ceo', target: 'cto' },
{ source: 'cto', target: 'dev1' }
]
};
Process Flow Diagram
const processData = {
nodes: [
{ id: 'start', name: 'Start', type: 'event' },
{ id: 'process1', name: 'Process Data', type: 'activity' },
{ id: 'decision', name: 'Valid?', type: 'gateway' },
{ id: 'end', name: 'End', type: 'event' }
],
links: [
{ source: 'start', target: 'process1' },
{ source: 'process1', target: 'decision' },
{ source: 'decision', target: 'end' }
]
};
🚀 Next Steps
- 📖 Read the D3.js official documentation: https://d3js.org/
- 🎨 Explore our existing components in
shared/d3-architecture-diagram/ - 🔧 Create your first custom diagram following the guide above
- 🎯 Test with real data from your domain
- 📱 Make it responsive for all screen sizes
Happy Diagramming! 🎉