Skip to content

Rxcthefirst/EdgeCraft

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

# EdgeCraft 🎨 **Advanced Graph Visualization Library for RDF and LPG** EdgeCraft is a powerful, modern graph visualization library designed for building sophisticated network diagrams with support for both Resource Description Framework (RDF) and Labeled Property Graph (LPG) models. It combines the simplicity of Cytoscape with the power of D3, offering advanced features like association classes, multiple layout algorithms, and a clean, intuitive API. ## ✨ Features - **Dual Graph Model Support**: Native support for both RDF triples and LPG structures - **Advanced Patterns**: Association classes for n-ary relationships - **Multiple Layout Algorithms**: Force-directed, hierarchical, circular, and grid layouts - **Rich Interactions**: Drag, zoom, pan, select with customizable behaviors - **Flexible Styling**: Function-based styling for dynamic visual properties - **TypeScript First**: Fully typed API with excellent IDE support - **Performance Optimized**: Efficient rendering for large graphs - **Extensible Architecture**: Easy to extend with custom layouts and renderers ## 📦 Installation ```bash npm install edgecraft ``` Or with yarn: ```bash yarn add edgecraft ``` ## 🚀 Quick Start ```typescript import { EdgeCraft } from 'edgecraft'; // Create a simple graph const graph = new EdgeCraft({ container: '#graph-container', data: { nodes: [ { id: 1, labels: ['Person'], properties: { name: 'Alice' } }, { id: 2, labels: ['Person'], properties: { name: 'Bob' } }, { id: 3, labels: ['Company'], properties: { name: 'Tech Corp' } } ], edges: [ { id: 'e1', source: 1, target: 2, label: 'KNOWS', properties: { since: 2020 } }, { id: 'e2', source: 1, target: 3, label: 'WORKS_AT', properties: { role: 'Engineer' } } ] }, layout: { type: 'force' } }); ``` ## 📚 Examples ### LPG (Labeled Property Graph) ```typescript import { EdgeCraft, LPGNode, LPGEdge } from 'edgecraft'; const nodes: LPGNode[] = [ { id: 'alice', labels: ['Person'], properties: { name: 'Alice', age: 30 } }, { id: 'bob', labels: ['Person'], properties: { name: 'Bob', age: 35 } }, { id: 'techcorp', labels: ['Company'], properties: { name: 'Tech Corp' } } ]; const edges: LPGEdge[] = [ { id: 'e1', source: 'alice', target: 'bob', label: 'KNOWS', properties: { since: 2015 }, directed: true }, { id: 'e2', source: 'alice', target: 'techcorp', label: 'WORKS_AT', properties: { position: 'Senior Engineer', since: 2020 } } ]; const graph = new EdgeCraft({ container: '#graph', data: { nodes, edges }, layout: { type: 'force', iterations: 500 }, nodeStyle: (node) => ({ fill: node.labels.includes('Person') ? '#4a90e2' : '#e74c3c', radius: 25, label: { text: node.properties.name, fontSize: 14, position: 'bottom' } }), edgeStyle: { stroke: '#95a5a6', strokeWidth: 2, arrow: 'forward' } }); ``` ### RDF (Resource Description Framework) ```typescript import { EdgeCraft, RDFNode, RDFTriple } from 'edgecraft'; const nodes: RDFNode[] = [ { id: 'alice', type: 'uri', value: 'http://example.org/alice' }, { id: 'bob', type: 'uri', value: 'http://example.org/bob' }, { id: 'name1', type: 'literal', value: 'Alice', datatype: 'xsd:string' }, { id: 'name2', type: 'literal', value: 'Bob', datatype: 'xsd:string' } ]; const triples: RDFTriple[] = [ { id: 't1', subject: 'alice', predicate: 'foaf:knows', object: 'bob' }, { id: 't2', subject: 'alice', predicate: 'foaf:name', object: 'name1' }, { id: 't3', subject: 'bob', predicate: 'foaf:name', object: 'name2' } ]; const graph = new EdgeCraft({ container: '#rdf-graph', data: { nodes, edges: triples }, layout: { type: 'hierarchical' }, nodeStyle: (node) => ({ fill: node.type === 'uri' ? '#3498db' : '#f39c12', shape: node.type === 'uri' ? 'circle' : 'rectangle', radius: node.type === 'uri' ? 20 : 15 }) }); ``` ### Custom Styling ```typescript const graph = new EdgeCraft({ container: '#graph', data: myData, nodeStyle: (node) => { // Dynamic styling based on node properties const degree = graph.getConnectedEdges(node.id).length; return { fill: degree > 5 ? '#e74c3c' : '#3498db', radius: 10 + degree * 2, stroke: '#2c3e50', strokeWidth: 2, label: { text: node.properties?.name || node.id, fontSize: 12, color: '#fff' } }; }, edgeStyle: (edge) => ({ stroke: edge.properties?.weight > 0.5 ? '#e74c3c' : '#95a5a6', strokeWidth: 1 + (edge.properties?.weight || 0) * 3, strokeDasharray: edge.properties?.type === 'temporary' ? '5,5' : undefined, arrow: 'forward', label: { text: edge.label, fontSize: 10, color: '#7f8c8d', backgroundColor: 'rgba(255,255,255,0.8)' } }) }); ``` ### Event Handling ```typescript // Node click graph.on('node-click', (event) => { console.log('Clicked node:', event.target); console.log('Node position:', event.position); }); // Node hover graph.on('node-mouseenter', (event) => { console.log('Hovering over:', event.target); }); // Drag events graph.on('node-dragstart', (event) => { console.log('Started dragging:', event.target); }); graph.on('node-drag', (event) => { console.log('Dragging:', event.target, 'to', event.position); }); graph.on('node-dragend', (event) => { console.log('Finished dragging:', event.target); }); // Background click graph.on('background-click', () => { graph.clearSelection(); }); ``` ### Dynamic Updates ```typescript // Add nodes dynamically graph.addNode({ id: 'new-node', labels: ['Person'], properties: { name: 'Charlie' } }); // Add edges graph.addEdge({ id: 'e-new', source: 'alice', target: 'new-node', label: 'KNOWS', properties: {} }); // Remove elements graph.removeNode('bob'); graph.removeEdge('e1'); // Update layout graph.setLayout({ type: 'circular' }); // Query the graph const neighbors = graph.getNeighbors('alice'); const allEdges = graph.getConnectedEdges('alice'); ``` ### View Control ```typescript // Fit entire graph in view graph.fitView(); // Center the graph graph.centerView(); // Zoom controls graph.zoomIn(); graph.zoomOut(); graph.resetZoom(); // Selection graph.selectNode('alice'); const selected = graph.getSelectedNodes(); graph.clearSelection(); ``` ## 🎨 Layout Algorithms ### Force-Directed Layout Simulates physical forces between nodes for organic-looking graphs. ```typescript graph.setLayout({ type: 'force', iterations: 300, nodeSpacing: 100 }); ``` ### Hierarchical Layout Arranges nodes in levels, ideal for trees and DAGs. ```typescript graph.setLayout({ type: 'hierarchical', levelSpacing: 150, nodeSpacing: 100 }); ``` ### Circular Layout Places nodes in a circle, great for showing relationships. ```typescript graph.setLayout({ type: 'circular' }); ``` ### Grid Layout Arranges nodes in a regular grid pattern. ```typescript graph.setLayout({ type: 'grid', nodeSpacing: 100 }); ``` ## 🔧 Configuration Options ```typescript interface EdgeCraftConfig { container: HTMLElement | string; // Container element or selector data?: GraphData; // Initial graph data layout?: LayoutConfig; // Layout algorithm config interaction?: InteractionConfig; // Interaction settings nodeStyle?: NodeStyle | StyleFunction; // Node visual styling edgeStyle?: EdgeStyle | StyleFunction; // Edge visual styling renderer?: RendererConfig; // Renderer configuration (see below) width?: number; // Canvas width height?: number; // Canvas height backgroundColor?: string; // Background color minZoom?: number; // Minimum zoom level maxZoom?: number; // Maximum zoom level } ``` ### Renderer Configuration EdgeCraft uses a **WebGL-first** approach (like Keylines) for optimal performance: ```typescript // Default behavior: WebGL with Canvas fallback const graph = new EdgeCraft({ container: '#graph', data: myData // Automatically uses WebGL if supported, falls back to Canvas }); // Explicit WebGL (with Canvas fallback if not supported) const graph = new EdgeCraft({ container: '#graph', data: myData, renderer: { type: 'webgl' // Tries WebGL, auto-falls back to Canvas } }); // Force Canvas renderer (useful for testing or specific requirements) const graph = new EdgeCraft({ container: '#graph', data: myData, renderer: { type: 'canvas', // Explicitly use Canvas renderer enableCache: true, enableDirtyRegions: true // Optimize Canvas performance } }); // Renderer with additional options const graph = new EdgeCraft({ container: '#graph', data: myData, renderer: { type: 'auto', // Default: WebGL-first with Canvas fallback pixelRatio: window.devicePixelRatio, // For high-DPI displays enableCache: true, // Cache rendered elements (Canvas only) enableDirtyRegions: true // Only re-render changed areas (Canvas only) } }); ``` **Renderer Types:** - **`'auto'` (default)**: Tries WebGL first, falls back to Canvas if not supported - **`'webgl'`**: Explicitly requests WebGL (falls back to Canvas if not available) - **`'canvas'`**: Forces Canvas renderer (good for compatibility or debugging) **Why WebGL-first?** - 🚀 GPU-accelerated rendering for better performance - 📊 Handles large graphs (10,000+ nodes) efficiently - ⚡ Smooth animations and interactions - 🔄 Automatic fallback ensures compatibility ## 📖 API Reference ### Graph Management - `setData(data: GraphData): void` - Replace entire graph - `getData(): GraphData` - Get current graph data - `addNode(node: GraphNode): void` - Add a node - `removeNode(nodeId): boolean` - Remove a node - `addEdge(edge: GraphEdge): void` - Add an edge - `removeEdge(edgeId): boolean` - Remove an edge ### Queries - `getNode(nodeId): GraphNode | undefined` - Get node by ID - `getEdge(edgeId): GraphEdge | undefined` - Get edge by ID - `getAllNodes(): GraphNode[]` - Get all nodes - `getAllEdges(): GraphEdge[]` - Get all edges - `getNeighbors(nodeId): GraphNode[]` - Get adjacent nodes - `getConnectedEdges(nodeId): GraphEdge[]` - Get connected edges - `queryTriples(subject?, predicate?, object?): RDFTriple[]` - RDF query ### View Control - `fitView(): void` - Fit graph to view - `centerView(): void` - Center the graph - `zoomIn(): void` - Zoom in - `zoomOut(): void` - Zoom out - `resetZoom(): void` - Reset zoom to 100% ### Events - `on(eventType: string, callback): void` - Register event listener - `off(eventType: string, callback): void` - Remove event listener ### Selection - `selectNode(nodeId): void` - Select a node - `clearSelection(): void` - Clear selection - `getSelectedNodes(): NodeId[]` - Get selected nodes ### Export - `toJSON(): string` - Export graph as JSON - `fromJSON(json: string): void` - Import graph from JSON - `exportSVG(): string` - Export as SVG string ## 🔍 RDF-Specific Features EdgeCraft provides excellent support for semantic web applications: ```typescript // Query triples by pattern const aliceTriples = graph.queryTriples('alice'); const nameTriples = graph.queryTriples(undefined, 'foaf:name'); const allKnows = graph.queryTriples(undefined, 'foaf:knows'); // Add triples programmatically graph.addTriple('alice', 'foaf:knows', 'charlie'); // Work with different node types const uriNodes = graph.getRDFNodes().filter(n => n.type === 'uri'); const literals = graph.getRDFNodes().filter(n => n.type === 'literal'); ``` ## 🏗️ Association Classes Support for n-ary relationships: ```typescript const data = { nodes: [ { id: 'alice', labels: ['Person'], properties: { name: 'Alice' } }, { id: 'bob', labels: ['Person'], properties: { name: 'Bob' } }, { id: 'project', labels: ['Project'], properties: { name: 'EdgeCraft' } } ], edges: [ { id: 'e1', source: 'alice', target: 'membership1', label: 'HAS_ROLE', properties: {} }, { id: 'e2', source: 'membership1', target: 'project', label: 'ON_PROJECT', properties: {} } ], associationClasses: [ { id: 'membership1', name: 'ProjectMembership', sourceEdges: ['e1', 'e2'], properties: { role: 'Lead Developer', since: '2023' } } ] }; ``` ## 🎯 Use Cases - **Knowledge Graphs**: Visualize semantic web data and ontologies - **Social Networks**: Display relationships between people and entities - **Data Lineage**: Track data flow and transformations - **Dependency Graphs**: Visualize software dependencies and relationships - **Organization Charts**: Display hierarchical structures - **Mind Maps**: Create and visualize concept relationships - **Network Diagrams**: Infrastructure and system architecture visualization ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## 📄 License MIT License - see LICENSE file for details ## 🔗 Links - [GitHub Repository](https://github.com/yourusername/edgecraft) - [Documentation](https://edgecraft.dev) - [Examples](https://edgecraft.dev/examples) - [Issue Tracker](https://github.com/yourusername/edgecraft/issues) ## 🙏 Acknowledgments EdgeCraft builds upon the excellent work of: - D3.js for force simulation and interactions - The graph visualization community --- Made with ❤️ for the graph visualization community# EdgeCraft

About

JavaScript Graph Visualization Library - Open Source LPG & RDF visualization

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages