vortx-gl 1.0.1 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,41 @@
1
1
  # VortxGL 🎨
2
2
 
3
- A high-performance, modular graph visualization engine built with **Vue 3**, **WebGL2**, and **TypeScript**. Optimized for extreme scale, this engine can handle **50,000+ nodes and edges** effortlessly at 60 FPS.
3
+ A world-class, high-performance graph visualization engine built with **Vue 3**, **WebGL2**, and **TypeScript**. Engineered for extreme scale and architectural flexibility, VortxGL effortlessly handles **100,000+ nodes and edges** while maintaining a locked 60 FPS.
4
+
5
+ ---
6
+
7
+ ## 🚀 Key Evolutionary Features
8
+
9
+ ### 🎬 Energy Flow Visualization
10
+
11
+ Bring your data to life with real-time particle animations along graph edges.
12
+
13
+ - **Dynamic Velocity**: Adjust stream speed in real-time.
14
+ - **Precision Filtering**: Target specific data flows by property and value (e.g., animate only `type: "transaction"`).
15
+ - **GPU-Ready**: Performance-optimized rendering that scales with your dataset.
16
+
17
+ ### 📁 Advanced Combo (Grouping) System
18
+
19
+ Full support for hierarchical data structures and interactive clustering.
20
+
21
+ - **Smart Hulls**: Automatically generated convex hulls for expanded groups.
22
+ - **Interactive Collapsing**: Swap complex clusters for intuitive summary nodes.
23
+ - **Cluster Translation**: Drag entire groups while preserving internal layouts.
24
+
25
+ ### ⛓️ Interactive Relation Builder
26
+
27
+ Engineered for semantic graph creation with real-time visual feedback.
28
+
29
+ - **Phantom Edges**: Real-time dashed preview line that follows the cursor during connection.
30
+ - **On-the-Fly Configuration**: Set labels, colors, and thickness via an interactive toast before finalizing.
31
+ - **Adaptive Labels**: Screen-space edge labels that automatically render for high-zoom clarity.
32
+
33
+ ### 🏎️ Tactical Optimization
34
+
35
+ Built with a performance-first mindset:
36
+
37
+ - **Screen-Space Projection Cache**: Eliminates redundant O(NodeCount) matrix operations for labels and effects.
38
+ - **Zero-Allocation Loops**: Uses specialized scratch buffers to minimize Garbage Collection impact.
4
39
 
5
40
  ---
6
41
 
@@ -15,7 +50,7 @@ npm install vortx-gl
15
50
  ### 2. Basic Usage (Vue 3)
16
51
 
17
52
  ```vue
18
- <script setup>
53
+ <script setup lang="ts">
19
54
  import { GraphCanvas } from "vortx-gl";
20
55
  import "vortx-gl/dist/vortx-gl.css";
21
56
 
@@ -25,12 +60,16 @@ const graphData = {
25
60
  data: {
26
61
  id: "1",
27
62
  label: "Node 1",
28
- color: "#ff4757",
29
- backgroundImage: "https://example.com/icon.png", // Optional icon
63
+ color: "#00ffcc",
64
+ backgroundImage: "https://example.com/icon.png",
30
65
  },
31
66
  },
32
67
  ],
33
- edges: [],
68
+ edges: [
69
+ {
70
+ data: { source: "1", target: "2", type: "transfer" },
71
+ },
72
+ ],
34
73
  };
35
74
  </script>
36
75
 
@@ -43,47 +82,36 @@ const graphData = {
43
82
 
44
83
  ---
45
84
 
46
- ## 🌐 Live Demo
85
+ ## 🌐 Live Demo & Docs
47
86
 
48
- 🚀 **Watch it in action**: [View the Live Demo](https://webgl-graph.vercel.app)
87
+ 🚀 **Experience the Speed**: [View the Live Demo](https://webgl-graph.vercel.app)
49
88
 
50
89
  ---
51
90
 
52
- ## 🚀 Key Features
53
-
54
- - **Massive Scale**: Leverages WebGL2 for smooth 60 FPS rendering of **50k+ elements**.
55
- - **Icon Support**: Render high-quality UI icons or images directly within nodes using `backgroundImage`.
56
- - **Advanced Interaction**: Precision GPU picking, box selection, and smooth camera controls.
57
- - **Worker-Powered Layouts**: Force-directed, Concentric, Radial, and Grid layouts computed in background workers.
58
- - **Hybrid Rendering**: Secondary overlay for crisp labels and custom UI.
59
-
60
- ---
91
+ ## 📊 Data Schema & Types
61
92
 
62
- ## 📊 Data Schema
63
-
64
- The engine uses a JSON format compatible with Cytoscape.js:
93
+ VortxGL uses a robust, TypeScript-first schema. All element metadata is stored in a dedicated `data` record for application use.
65
94
 
66
95
  ```json
67
96
  {
68
97
  "nodes": [
69
98
  {
70
99
  "data": {
71
- "id": "1",
72
- "label": "A",
73
- "color": "#000",
74
- "width": 50,
75
- "height": 50,
76
- "backgroundImage": "data:image/png;base64,..."
100
+ "id": "node-1",
101
+ "label": "Engineering",
102
+ "color": "#ff4757",
103
+ "backgroundImage": "data:image/png;base64,...",
104
+ "metadata": { "status": "active" }
77
105
  }
78
106
  }
79
107
  ],
80
108
  "edges": [
81
109
  {
82
110
  "data": {
83
- "id": "e1-2",
84
- "source": "1",
85
- "target": "2",
86
- "label": "Connection"
111
+ "id": "edge-1",
112
+ "source": "node-1",
113
+ "target": "node-2",
114
+ "label": "Data Link"
87
115
  }
88
116
  }
89
117
  ]
@@ -92,16 +120,438 @@ The engine uses a JSON format compatible with Cytoscape.js:
92
120
 
93
121
  ---
94
122
 
95
- ## ⌨️ Shortcuts
123
+ ## 🎨 Visual Polish
124
+
125
+ VortxGL provides rich options for making your graph look premium and intuitive.
126
+
127
+ ### 1. Icons & Images
128
+ Nodes can render text-based icons (emojis) or high-resolution images.
129
+
130
+ ```typescript
131
+ engine.addNode({
132
+ id: "node-1",
133
+ icon: "📂", // Renders text/emoji in center
134
+ image: "url...", // Renders rounded image inside
135
+ size: 60
136
+ });
137
+ ```
138
+
139
+ ### 2. Color Formats
140
+ Colors accept standard CSS hex strings or precision arrays for hardware-level control.
141
+
142
+ ```typescript
143
+ // CSS Hex
144
+ color: "#ff4757"
145
+
146
+ // RGBA Array (0-1 range)
147
+ color: [1.0, 0.28, 0.34, 1.0]
148
+
149
+ // Transparent
150
+ color: [0, 0, 0, 0] // Useful for "ghost" nodes
151
+ ```
152
+
153
+ ### 3. Theme Switching
154
+ The engine supports built-in Dark and Light mode, affecting the background clear color and label contrast automatically.
155
+
156
+ ```typescript
157
+ engine.setTheme("light"); // Switches to light background
158
+ ```
159
+
160
+ ---
161
+
162
+ ## 📁 Combo Management
163
+
164
+ Combos (Groups) allow you to cluster related nodes into logical units. They support two modes: **Expanded** (showing a bounding hull) and **Collapsed** (showing a summary representative node).
165
+
166
+ ### 1. Creating a Group
167
+ Groups are created by specifying a unique ID and a list of node IDs to include.
168
+
169
+ ```typescript
170
+ engine.createGroup("group-alpha", "Engineers", ["node-1", "node-2", "node-3"]);
171
+ ```
172
+
173
+ ### 2. Collapsing & Expanding
174
+ Collapsing a group hides all member nodes except for one **representative**, which snaps to the centroid of the group.
175
+
176
+ ```typescript
177
+ // Programmatically toggle state
178
+ engine.toggleComboCollapse("group-alpha");
179
+
180
+ // Listen for collapse events
181
+ engine.on('combo:update', (data) => {
182
+ console.log(`Group ${data.id} is now ${data.state ? 'collapsed' : 'expanded'}`);
183
+ });
184
+ ```
185
+
186
+ ### 3. Interaction Logic
187
+ - **Dragging**: When a group is collapsed, dragging its representative moves all hidden members in sync.
188
+ - **Hulls**: When expanded, a convex hull is automatically rendered around the members with customizable padding and color.
189
+ - **Picking**: You can select a group by clicking on its hull (expanded) or its representative node (collapsed).
190
+
191
+ ---
192
+
193
+ ## ⌨️ Pro Shortcuts
96
194
 
97
195
  | Command | Action |
98
196
  | :--------------- | :------------------------- |
99
197
  | **Left Click** | Select Node / Edge / Combo |
100
- | **Drag** | Pan the view |
101
- | **Scroll** | Zoom at mouse position |
102
- | **Shift + Drag** | Box Selection |
103
- | **Right Click** | Context Menu (Radial) |
104
- | **F** | Fit to View |
198
+ | **Drag** | Pan the world |
199
+ | **Scroll** | Zoom at mouse focal point |
200
+ | **Shift + Drag** | Precise Box Selection |
201
+ | **Radial Right Click** | Contextual Command Menu |
202
+ | **F** | Snap to Fit View |
203
+
204
+ ---
205
+
206
+ ## 🔘 Context Menus
207
+
208
+ VortxGL is designed to work seamlessly with domestic UI frameworks (Vue, React). Instead of drawing menus on the WebGL canvas, it is recommended to use standard DOM components positioned over the canvas.
209
+
210
+ ### 1. Triggering Menus
211
+ Listen for the `contextmenu` event on the canvas. Use `engine.pick()` or `engine.getEdgeAt()` to identify the element under the cursor.
212
+
213
+ ```typescript
214
+ canvas.addEventListener('contextmenu', (e) => {
215
+ e.preventDefault();
216
+ const rect = canvas.getBoundingClientRect();
217
+ const x = e.clientX - rect.left;
218
+ const y = e.clientY - rect.top;
219
+
220
+ // Identify target
221
+ const nodeId = engine.pick(x, y);
222
+ const edgeId = engine.getEdgeAt(x, y);
223
+
224
+ // Show your Vue/React menu at e.clientX/Y
225
+ showMenu({ x: e.clientX, y: e.clientY, target: nodeId || edgeId });
226
+ });
227
+ ```
228
+
229
+ ### 2. Customizing Menu Items
230
+ You can configure the segments of the circular menu for nodes, edges, and combos through the engine instance.
231
+
232
+ ```typescript
233
+ engine.setRadialMenu('node', [
234
+ { label: 'Inspect', icon: 'search', action: 'inspect' },
235
+ { label: 'Delete', icon: 'trash-2', action: 'delete' },
236
+ { label: 'Highlight', icon: 'zap', action: 'highlight' }
237
+ ]);
238
+ ```
239
+
240
+ ### 3. Group HUD (Heads-Up Display)
241
+ For combos (groups), the engine draws a built-in HUD with an expand/collapse button. You can detect clicks on these HUD elements using `pickHUD()`.
242
+
243
+ ```typescript
244
+ engine.on('node:mousedown', (e) => {
245
+ const hudAction = engine.pickHUD(e.x, e.y);
246
+ if (hudAction) {
247
+ if (hudAction.action === 'expand') {
248
+ engine.toggleComboCollapse(hudAction.comboId);
249
+ }
250
+ }
251
+ });
252
+ ```
253
+
254
+ ### 4. Interactive Connection Workflow
255
+
256
+ VortxGL includes a built-in workflow for creating new relations between nodes with real-time feedback.
257
+
258
+ 1. **Trigger**: Call `engine.startConnect(sourceNodeId)` to enter connection mode.
259
+ 2. **Preview**: A "Phantom Edge" (dashed line) will follow the cursor from the source node to the mouse position.
260
+ 3. **Configure**: Users can set properties like `label` and `color` during the preview phase.
261
+ 4. **Complete**: Clicking a target node finalizes the connection and creates a permanent "Styled Edge".
262
+
263
+ ---
264
+
265
+
266
+ ## 🏗️ Graph Mutation
267
+
268
+ VortxGL provides a high-performance imperative API for modifying the graph in real-time. Changes are immediately synced to GPU buffers using minimal memory copies.
269
+
270
+ ### 1. Adding Elements
271
+ ```typescript
272
+ // Add a node
273
+ engine.addNode({
274
+ id: "node-1",
275
+ label: "New Node",
276
+ position: { x: 100, y: 100 },
277
+ color: "#ff00ff"
278
+ });
279
+
280
+ // Add an edge
281
+ engine.addEdge({
282
+ source: "node-1",
283
+ target: "node-2",
284
+ label: "Connected"
285
+ });
286
+ ```
287
+
288
+ ### 2. Updating Elements
289
+ Updates are partial; you only need to provide the fields you want to change.
290
+ ```typescript
291
+ engine.updateNode({
292
+ id: "node-1",
293
+ color: "#00ff00", // Change color
294
+ label: "Updated Name"
295
+ });
296
+
297
+ engine.updateEdge({
298
+ id: "edge-1",
299
+ label: "New Relationship"
300
+ });
301
+ ```
302
+
303
+ ### 3. Removing Elements
304
+ ```typescript
305
+ // Removes node and all connected edges
306
+ engine.removeNode("node-1");
307
+
308
+ // Removes a single edge
309
+ engine.removeEdge("edge-1");
310
+
311
+ // Complete reset
312
+ engine.clear();
313
+ ```
314
+
315
+ ### 3. Visual Properties Reference
316
+
317
+ | Property | Type | Target | Description |
318
+ |---|---|---|---|
319
+ | `label` | string | Both | Primary text label (Edges show at >30% zoom) |
320
+ | `size` | number | Node | Diameter of the node circle |
321
+ | `width` | number | Both | Bounding width for node labels |
322
+ | `customSize` | number | Edge | Precision line thickness (supports <1 and >10) |
323
+ | `customColor`| string | Edge | Per-edge override color (HEX/RGBA) |
324
+ | `color` | string | Node | CSS Hex or RGBA value |
325
+ | `icon` | string | Node | Lucide icon name or Emoji |
326
+ | `image` | string | Node | URL for an image shown inside the node |
327
+ | `opacity`| number | Both | Global transparency (0-1) |
328
+
329
+ ```typescript
330
+ // Style a large node
331
+ engine.updateNode({
332
+ id: "node-1",
333
+ label: "Large Server",
334
+ size: 80, // Diameter
335
+ width: 120, // Label boundary width
336
+ color: "#ff3300"
337
+ });
338
+
339
+ // Create a premium styled connection
340
+ engine.addEdge({
341
+ source: "node-1",
342
+ target: "node-2",
343
+ label: "Critical Link",
344
+ data: {
345
+ customColor: "#ff00ff", // Override WebGL global color
346
+ customSize: 4.5 // Precise thickness in pixels
347
+ }
348
+ });
349
+ ```
350
+
351
+ ---
352
+
353
+ ## 🔍 Querying Elements
354
+
355
+ Retrieve element data from the engine for inspection or state management.
356
+
357
+ ### 1. Selection by ID
358
+ ```typescript
359
+ const node = engine.getNode("node-1");
360
+ console.log(node.position, node.label);
361
+ ```
362
+
363
+ ### 2. Selection by Class
364
+ Retrieve groups of elements that share a specific class.
365
+
366
+ ```typescript
367
+ // Get all critical servers
368
+ const criticalNodes = engine.getNodesByClass("critical");
369
+
370
+ // Get all standard cables
371
+ const standardEdges = engine.getEdgesByClass("standard-link");
372
+ ```
373
+
374
+ ### 3. Global Retrieval
375
+ ```typescript
376
+ const allNodes = engine.getAllNodes();
377
+ const allEdges = engine.getAllEdges();
378
+ ```
379
+
380
+ ---
381
+
382
+ ## 🎨 Styling with Classes
383
+
384
+ VortxGL supports a high-performance stylesheet system, allowing you to define visual presets and apply them via class names, similar to CSS or Cytoscape.
385
+
386
+ ### 1. Defining a Stylesheet
387
+ A stylesheet is a dictionary where keys are class names and values are style objects. Use `engine.setStylesheet()` to apply it globally.
388
+
389
+ ```typescript
390
+ const theme = {
391
+ 'critical': { color: '#ff4757', size: 60, icon: '⚠️' } ,
392
+ 'server': { color: '#2f3542', size: 45, icon: '🖥️' },
393
+ 'standard-link': { color: 'rgba(255,255,255,0.2)' }
394
+ };
395
+
396
+ engine.setStylesheet(theme);
397
+ ```
398
+
399
+ ### 2. Applying Classes
400
+ Apply classes when adding or updating elements. Multiple classes can be applied as an array; later classes override previous ones.
401
+
402
+ ```typescript
403
+ engine.addNode({
404
+ id: "node-1",
405
+ classes: ["server", "critical"],
406
+ label: "Database 01"
407
+ });
408
+
409
+ engine.addEdge({
410
+ source: "node-1",
411
+ target: "node-2",
412
+ classes: ["standard-link"]
413
+ });
414
+ ```
415
+
416
+ ### 3. Priority Rules
417
+ Visual properties are applied in the following order of precedence:
418
+ 1. **Explicit Properties**: Properties set directly on the node (e.g., `color: '#fff'`) always win.
419
+ 2. **Class Styles**: Properties defined in the stylesheet for the applied classes.
420
+ 3. **Engine Defaults**: Hardcoded fallback values.
421
+
422
+ ---
423
+
424
+ ## ⚡ Energy Flow Animation
425
+
426
+ VortxGL includes a custom, hardware-accelerated "Energy Flow" animation for highlighting data movements along edges.
427
+
428
+ ### 1. Basic Configuration
429
+ ```typescript
430
+ engine.setFlowConfig({
431
+ enabled: true,
432
+ velocity: 0.005,
433
+ size: 2,
434
+ color: "#00ffcc"
435
+ });
436
+ ```
437
+
438
+ ### 2. Selective Flow (Advanced)
439
+ You can restrict the animation to only run on edges connected to the currently selected nodes. This is extremely useful for tracing paths or focusing on specific network segments.
440
+
441
+ ```typescript
442
+ engine.setFlowConfig({
443
+ enabled: true,
444
+ selectedOnly: true
445
+ });
446
+ ```
447
+
448
+ ### 3. All Options
449
+ | Property | Type | Description |
450
+ |---|---|---|
451
+ | `enabled` | boolean | Toggle the animation |
452
+ | `velocity` | number | Speed of particles (0.001 - 0.01 recommended) |
453
+ | `size` | number | Radius of particles in pixels |
454
+ | `opacity` | number | Transparency (0 - 1) |
455
+ | `pulse` | boolean | Adds a subtle breathing effect to particles |
456
+ | `selectedOnly`| boolean | Show only on edges of selected nodes |
457
+
458
+ ---
459
+
460
+ ## 🏗️ Events & Interactivity
461
+
462
+ VortxGL features a powerful, Cytoscape-inspired event system for deep integration with your application logic.
463
+
464
+ ### 1. Subscribing to Events
465
+ Use the `on()` API to listen for interactions. Use the returned function to unsubscribe.
466
+
467
+ ```typescript
468
+ // Subscribe
469
+ const unsub = engine.on('node:click', ({ id }) => {
470
+ console.log('Clicked node:', id);
471
+ });
472
+
473
+ // Unsubscribe when component is destroyed
474
+ unsub();
475
+ ```
476
+
477
+ ### 2. Available Events
478
+ | Category | Event Keys | Description |
479
+ | :--- | :--- | :--- |
480
+ | **Nodes** | `node:click`, `node:hover`, `node:drag`, `node:select` | Individual element interactions |
481
+ | **Edges** | `edge:click`, `edge:hover`, `edge:select` | Edge-specific interactions |
482
+ | **Combos** | `combo:click`, `combo:hover`, `combo:select` | Group-specific interactions |
483
+ | **Viewport** | `graph:click`, `graph:pan`, `graph:zoom`, `viewport` | Global camera movement |
484
+ | **Selection**| `boxstart`, `boxselect`, `boxend` | Marquee/Box selection lifecycle |
485
+
486
+ ---
487
+
488
+ ## 📸 Viewport & Camera
489
+
490
+ Control the view programmatically to create cinematic transitions or automated "focus" actions.
491
+
492
+ ### 1. Focus & Fit
493
+ ```typescript
494
+ // Auto-scale and center to show the entire graph
495
+ engine.fitToView();
496
+
497
+ // Move camera to a specific world coordinate
498
+ engine.setCameraCenter(0, 0);
499
+ ```
500
+
501
+ ### 2. Zoom Controls
502
+ ```typescript
503
+ engine.zoomIn();
504
+ engine.zoomOut();
505
+
506
+ // Precise focal zoom (screen coordinates)
507
+ engine.zoomAt(mouseX, mouseY, delta);
508
+ ```
509
+
510
+ ---
511
+
512
+ ## 🧬 Layouts & Batch Updates
513
+
514
+ VortxGL provides built-in geometric layouts and supports seamless integration with external layout engines (like Cytoscape.js or d3-force).
515
+
516
+ ### 1. Built-in Geometric Layouts
517
+ Trigger fast, animated layouts directly from the engine instance.
518
+
519
+ ```typescript
520
+ // Arrange all nodes in a circle
521
+ engine.runLayout('circle');
522
+
523
+ // Arrange nodes in a grid
524
+ engine.runLayout('grid');
525
+
526
+ // Random scatter
527
+ engine.runLayout('random');
528
+ ```
529
+
530
+ ### 2. Layouts on Selection
531
+ You can restrict any built-in layout to only affect currently selected elements, keeping the rest of the graph anchored.
532
+
533
+ ```typescript
534
+ engine.runLayout('circle', { selectedOnly: true });
535
+ ```
536
+
537
+ ### 3. External Layouts (e.g. Cytoscape)
538
+ For complex force-directed or hierarchical layouts, calculate positions externally and sync them:
539
+
540
+ #### Batch Sync (Most Efficient)
541
+ Use `setData` for an O(1) buffer swap when a layout finishes.
542
+
543
+ ```typescript
544
+ engine.setData(newPositions, newColors, newIds, metadata, edgeIndices);
545
+ ```
546
+
547
+ #### Incremental Sync (Real-time Animation)
548
+ For live layout animations, use `updateNode` in your layout's tick function.
549
+
550
+ ```typescript
551
+ nodes.forEach(n => {
552
+ engine.updateNode({ id: n.id, position: { x: n.x, y: n.y } });
553
+ });
554
+ ```
105
555
 
106
556
  ---
107
557
 
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Handler function that consumes event data.
3
+ * T defaults to `unknown` for maximum safety.
4
+ */
5
+ export type EventHandler<T = unknown> = (data: T) => void;
6
+ /**
7
+ * Lightweight typed EventEmitter used internally by GraphEngine
8
+ * to expose a clean `engine.on('node:click', handler)` API.
9
+ */
10
+ export declare class EventEmitter {
11
+ private listeners;
12
+ /**
13
+ * Subscribe to an event.
14
+ * @param event The event unique key.
15
+ * @param handler Function to execute when the event fires.
16
+ * @returns An unsubscribe function for convenient cleanup.
17
+ */
18
+ on<T = unknown>(event: string, handler: EventHandler<T>): () => void;
19
+ /**
20
+ * Unsubscribe a specific handler from an event.
21
+ */
22
+ off<T = unknown>(event: string, handler: EventHandler<T>): void;
23
+ /**
24
+ * @internal
25
+ * Fire an event to all current subscribers.
26
+ */
27
+ emit<T = unknown>(event: string, data?: T): void;
28
+ /**
29
+ * Remove all handlers for a specific event, or all events if no name given.
30
+ */
31
+ removeAllListeners(event?: string): void;
32
+ }
@@ -0,0 +1,26 @@
1
+ import type { GraphEngine } from "./renderer";
2
+ export declare class InteractionManager {
3
+ private lastMouse;
4
+ private isPanning;
5
+ private engine;
6
+ private canvas;
7
+ private lastTouchDistance;
8
+ private lastTouchMidpoint;
9
+ private isTouching;
10
+ private touchStartTime;
11
+ private touchStartPos;
12
+ private longPressTimer;
13
+ private isLongPress;
14
+ private isDraggingCombo;
15
+ constructor(engine: GraphEngine, canvas: HTMLCanvasElement);
16
+ private setupListeners;
17
+ private handleMouseDown;
18
+ private handleMouseMove;
19
+ private handleMouseUp;
20
+ private handleWheel;
21
+ private handleTouchStart;
22
+ private handleTouchMove;
23
+ private handleTouchEnd;
24
+ private clearLongPress;
25
+ private triggerContextMenu;
26
+ }