D3 Universal Diagrams
Documentation for Developers
Universal D3 Diagrams System
The Universal D3 Diagrams system provides a flexible, reusable way to create interactive diagrams from simple JSON data. This system can handle any type of network diagram, from architecture diagrams to organizational charts.
🚀 Quick Start
Basic Usage in Angular Components
import { D3UniversalDiagramComponent } from './shared/d3-universal-diagram/d3-universal-diagram.component';
// In your component
export class MyComponent {
diagramData = {
nodes: [
{ id: 'node1', name: 'Frontend', category: 'ui' },
{ id: 'node2', name: 'Backend', category: 'api' },
{ id: 'node3', name: 'Database', category: 'storage' }
],
links: [
{ source: 'node1', target: 'node2' },
{ source: 'node2', target: 'node3' }
],
categories: {
ui: { color: '#3B82F6', label: 'User Interface' },
api: { color: '#10B981', label: 'API Layer' },
storage: { color: '#F59E0B', label: 'Data Storage' }
}
};
}
<app-d3-universal-diagram
[data]="diagramData"
title="System Architecture"
[width]="1000"
[height]="600"
[showLegend]="true"
[showControls]="true">
</app-d3-universal-diagram>
📊 Data Structure
Basic Structure
{
"title": "My Diagram",
"nodes": [
{
"id": "unique-id",
"name": "Display Name",
"category": "optional-category",
"color": "#optional-color",
"size": 50,
"description": "Optional description"
}
],
"links": [
{
"from": "source-node-id",
"to": "target-node-id",
"weight": 1,
"color": "#optional-color"
}
],
"categories": {
"category-name": {
"color": "#3B82F6",
"label": "Display Label"
}
},
"settings": {
"nodeSize": 50,
"linkDistance": 120,
"chargeStrength": -800,
"showLegend": true,
"allowDrag": true,
"allowZoom": true
}
}
🎨 Examples
1. Simple Network Diagram
{
"title": "Simple Network",
"nodes": [
{ "id": "server", "name": "Web Server", "category": "infrastructure" },
{ "id": "db", "name": "Database", "category": "storage" },
{ "id": "cache", "name": "Cache", "category": "storage" }
],
"links": [
{ "from": "server", "to": "db" },
{ "from": "server", "to": "cache" }
],
"categories": {
"infrastructure": { "color": "#3B82F6", "label": "Infrastructure" },
"storage": { "color": "#10B981", "label": "Storage" }
}
}
2. Team Organization Chart
{
"title": "Team Structure",
"nodes": [
{ "id": "pm", "name": "Project Manager", "category": "management" },
{ "id": "lead", "name": "Tech Lead", "category": "management" },
{ "id": "dev1", "name": "Frontend Dev", "category": "developer" },
{ "id": "dev2", "name": "Backend Dev", "category": "developer" },
{ "id": "qa", "name": "QA Engineer", "category": "quality" }
],
"links": [
{ "from": "pm", "to": "lead" },
{ "from": "lead", "to": "dev1" },
{ "from": "lead", "to": "dev2" },
{ "from": "lead", "to": "qa" }
],
"categories": {
"management": { "color": "#EF4444", "label": "Management" },
"developer": { "color": "#3B82F6", "label": "Developers" },
"quality": { "color": "#10B981", "label": "Quality" }
}
}
3. Data Flow Process
{
"title": "Data Processing Workflow",
"nodes": [
{ "id": "input", "name": "User Input", "category": "input", "size": 40 },
{ "id": "validate", "name": "Validation", "category": "process" },
{ "id": "transform", "name": "Transform", "category": "process" },
{ "id": "store", "name": "Store Data", "category": "storage" },
{ "id": "output", "name": "Response", "category": "output", "size": 40 }
],
"links": [
{ "from": "input", "to": "validate", "weight": 2 },
{ "from": "validate", "to": "transform" },
{ "from": "transform", "to": "store" },
{ "from": "store", "to": "output", "weight": 2 }
],
"categories": {
"input": { "color": "#10B981", "label": "Input" },
"process": { "color": "#F59E0B", "label": "Process" },
"storage": { "color": "#3B82F6", "label": "Storage" },
"output": { "color": "#8B5CF6", "label": "Output" }
},
"settings": {
"nodeSize": 45,
"linkDistance": 100,
"chargeStrength": -600
}
}
🛠️ Using the JSON Loader Service
Loading from JSON String
import { JsonDiagramLoaderService } from './shared/d3-universal-diagram/json-diagram-loader.service';
export class MyComponent {
constructor(private diagramLoader: JsonDiagramLoaderService) {}
loadDiagramFromJson(jsonString: string) {
const diagramData = this.diagramLoader.fromJsonString(jsonString);
this.currentDiagram = diagramData;
}
loadDiagramFromUrl(url: string) {
this.diagramLoader.fromUrl(url).then(data => {
this.currentDiagram = data;
});
}
generateTemplate() {
const template = this.diagramLoader.generateTemplate();
console.log(JSON.stringify(template, null, 2));
}
}
Validation
const validationResult = this.diagramLoader.validateDiagramData(myData);
if (!validationResult.valid) {
console.error('Validation errors:', validationResult.errors);
}
🎛️ Configuration Options
Node Properties
- id (required): Unique identifier for the node
- name (required): Display name for the node
- category (optional): Category for color coding and legend
- color (optional): Custom color (overrides category color)
- size (optional): Custom node size (overrides default)
- description (optional): Tooltip or additional information
Link Properties
- from/source (required): Source node ID
- to/target (required): Target node ID
- weight (optional): Link thickness multiplier
- color (optional): Custom link color
Global Settings
- nodeSize: Default size for all nodes (default: 50)
- linkDistance: Distance between connected nodes (default: 120)
- chargeStrength: Force between nodes - negative = repel (default: -800)
- collisionRadius: Minimum distance between nodes (default: 60)
- showLegend: Display category legend (default: true)
- allowDrag: Enable node dragging (default: true)
- allowZoom: Enable zoom and pan (default: true)
🎨 Visual Customization
Color Categories
Define reusable color schemes:
{
"categories": {
"frontend": { "color": "#3B82F6", "label": "Frontend" },
"backend": { "color": "#10B981", "label": "Backend" },
"database": { "color": "#F59E0B", "label": "Database" },
"external": { "color": "#EF4444", "label": "External" }
}
}
Node Sizes
Control visual hierarchy:
{
"nodes": [
{ "id": "main", "name": "Main Server", "size": 80 },
{ "id": "worker", "name": "Worker", "size": 40 },
{ "id": "monitor", "name": "Monitor", "size": 30 }
]
}
Link Weights
Show relationship strength:
{
"links": [
{ "from": "api", "to": "db", "weight": 3 },
{ "from": "api", "to": "cache", "weight": 1 }
]
}
🔧 Advanced Usage
Dynamic Data Loading
export class DiagramComponent {
diagramData$ = this.http.get<any>('/api/diagram-data').pipe(
map(data => this.diagramLoader.fromSimpleJson(data))
);
}
Interactive Features
The component automatically includes:
- Hover Effects: Highlight connected nodes and links
- Drag Support: Move nodes around
- Zoom/Pan: Navigate large diagrams
- Click Events: Access node information (check browser console)
Controls
Three built-in control buttons:
- Reset View: Return to original zoom/position
- Center: Center the diagram in the viewport
- Fit Screen: Auto-scale to fit all nodes
📱 Responsive Design
The component includes responsive breakpoints:
- Mobile devices: Smaller controls and simplified layout
- Tablet/Desktop: Full feature set with optimal spacing
🚀 Performance Tips
Large Datasets: For 100+ nodes, consider:
- Reducing
chargeStrength(less negative) - Increasing
linkDistance - Disabling animations temporarily
- Reducing
Memory Management:
- Clear old diagram data when switching
- Use OnPush change detection
- Destroy subscriptions properly
Optimization:
- Pre-calculate node positions for static diagrams
- Use
trackByfunctions in templates - Implement virtual scrolling for very large datasets
🎯 Use Cases
Perfect for visualizing:
- Software Architecture: Services, databases, APIs
- Team Organization: Reporting structures, team relationships
- Process Flows: Workflows, data pipelines, business processes
- Network Topology: Infrastructure, dependencies, connections
- Project Dependencies: Libraries, modules, build order
- Knowledge Maps: Concepts, relationships, hierarchies
🔄 Migration from Architecture Diagram
If you're currently using the architecture-specific component:
// Old way
<app-d3-architecture-diagram [data]="nxData">
// New way
<app-d3-universal-diagram [data]="universalData">
The universal system is backward compatible and more flexible!
🆘 Troubleshooting
Common Issues
- Nodes not appearing: Check that all node IDs are unique
- Links not connecting: Verify source/target IDs match node IDs exactly
- Colors not showing: Ensure category names in nodes match category definitions
- Performance issues: Reduce node count or adjust force simulation parameters
Debug Mode
Add console logging to track issues:
const validationResult = this.diagramLoader.validateDiagramData(data);
console.log('Validation:', validationResult);
Ready to create amazing interactive diagrams! 🎉