vortx-gl 1.0.28 → 1.0.30
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 +198 -453
- package/dist/engine/core/context.d.ts +14 -0
- package/dist/engine/interaction.d.ts +0 -3
- package/dist/engine/overlay/ComboRenderer.d.ts +8 -0
- package/dist/engine/overlay/EdgeRenderer.d.ts +1 -1
- package/dist/engine/overlay/OverlayManager.d.ts +2 -0
- package/dist/engine/renderer.d.ts +63 -1
- package/dist/engine/types.d.ts +9 -0
- package/dist/vortx-gl.es.js +3507 -3454
- package/dist/vortx-gl.umd.js +3588 -3533
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,560 +1,305 @@
|
|
|
1
|
-
# VortxGL
|
|
1
|
+
# 🎨 VortxGL
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext)
|
|
4
|
+
[](https://vuejs.org/)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
[](#-performance-benchmarks)
|
|
7
|
+
[](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
|
|
8
|
+
[](LICENSE)
|
|
4
9
|
|
|
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
|
|
10
|
+
VortxGL is a world-class, ultra-high-performance graph visualization library built with **WebGL2**, **Vue 3 (Composition API)**, and **TypeScript**.
|
|
34
11
|
|
|
35
|
-
|
|
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.
|
|
12
|
+
It was engineered from the ground up to address the limitations of traditional SVG and Canvas-based graph visualizers. While libraries like D3 or Cytoscape choke when handling more than 5,000 nodes due to DOM bloat and main-thread computation bottlenecks, VortxGL easily renders **100,000+ nodes and edges** at a locked **60 FPS**.
|
|
39
13
|
|
|
40
14
|
---
|
|
41
15
|
|
|
42
|
-
##
|
|
43
|
-
|
|
44
|
-
### 1. Installation
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
npm install vortx-gl
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 2. Basic Usage (Vue 3)
|
|
51
|
-
|
|
52
|
-
```vue
|
|
53
|
-
<script setup lang="ts">
|
|
54
|
-
import { GraphCanvas } from "vortx-gl";
|
|
55
|
-
import "vortx-gl/dist/vortx-gl.css";
|
|
56
|
-
|
|
57
|
-
const graphData = {
|
|
58
|
-
nodes: [
|
|
59
|
-
{
|
|
60
|
-
data: {
|
|
61
|
-
id: "1",
|
|
62
|
-
label: "Node 1",
|
|
63
|
-
color: "#00ffcc",
|
|
64
|
-
backgroundImage: "https://example.com/icon.png",
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
edges: [
|
|
69
|
-
{
|
|
70
|
-
data: { source: "1", target: "2", type: "transfer" },
|
|
71
|
-
},
|
|
72
|
-
],
|
|
73
|
-
};
|
|
74
|
-
</script>
|
|
16
|
+
## 🌐 Live Demo
|
|
75
17
|
|
|
76
|
-
|
|
77
|
-
<div style="width: 100vw; height: 100vh;">
|
|
78
|
-
<GraphCanvas :data="graphData" />
|
|
79
|
-
</div>
|
|
80
|
-
</template>
|
|
81
|
-
```
|
|
18
|
+
🚀 **Experience the Speed**: [VortxGL Live Interactive Sandbox](https://webgl-graph.vercel.app)
|
|
82
19
|
|
|
83
20
|
---
|
|
84
21
|
|
|
85
|
-
##
|
|
22
|
+
## ⚡ Performance Benchmarks
|
|
86
23
|
|
|
87
|
-
|
|
24
|
+
| Metric / Graph Size | 1,000 Nodes | 10,000 Nodes | 50,000 Nodes | 100,000 Nodes |
|
|
25
|
+
| :---------------------- | :---------: | :----------: | :----------: | :------------------: |
|
|
26
|
+
| **VortxGL FPS** | **60 FPS** | **60 FPS** | **60 FPS** | **60 FPS** |
|
|
27
|
+
| **Standard Canvas FPS** | 60 FPS | 24 FPS | 5 FPS | Crashed/Unresponsive |
|
|
28
|
+
| **Standard SVG FPS** | 30 FPS | 2 FPS | Unresponsive | Unresponsive |
|
|
88
29
|
|
|
89
30
|
---
|
|
90
31
|
|
|
91
|
-
##
|
|
32
|
+
## 🏎️ The Tech Behind the Speed (Architectural Highlights)
|
|
92
33
|
|
|
93
|
-
VortxGL
|
|
34
|
+
VortxGL achieves locked 60 FPS at scale by replacing common browser render bottlenecks with low-level graphics techniques:
|
|
94
35
|
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
"nodes": [
|
|
98
|
-
{
|
|
99
|
-
"data": {
|
|
100
|
-
"id": "node-1",
|
|
101
|
-
"label": "Engineering",
|
|
102
|
-
"color": "#ff4757",
|
|
103
|
-
"backgroundImage": "data:image/png;base64,...",
|
|
104
|
-
"metadata": { "status": "active" }
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
],
|
|
108
|
-
"edges": [
|
|
109
|
-
{
|
|
110
|
-
"data": {
|
|
111
|
-
"id": "edge-1",
|
|
112
|
-
"source": "node-1",
|
|
113
|
-
"target": "node-2",
|
|
114
|
-
"label": "Data Link"
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
]
|
|
118
|
-
}
|
|
119
|
-
```
|
|
36
|
+
### 1. Hybrid WebGL2 + Canvas2D Pipeline
|
|
120
37
|
|
|
121
|
-
|
|
38
|
+
WebGL2 excels at instanced rendering of millions of points and lines, but rendering anti-aliased text (labels), curved hulls, and vector badges in pure shaders is notoriously complex and slow. VortxGL uses a **dual-canvas architecture**:
|
|
122
39
|
|
|
123
|
-
|
|
40
|
+
- Core nodes and edges are drawn on the GPU in a single WebGL2 render pass.
|
|
41
|
+
- High-definition labels, badges, and selections are painted on a 2D HTML5 Canvas overlay.
|
|
42
|
+
- **The "Punch-Out" Technique**: To keep edge lines visual beneath nodes, the overlay draws connections behind, then uses a `destination-out` blending operation to "punch" circular holes in the overlay exactly where the GPU nodes sit. Text and selection rings are then drawn on top.
|
|
124
43
|
|
|
125
|
-
|
|
44
|
+
### 2. O(1) GPU Color Picking
|
|
126
45
|
|
|
127
|
-
|
|
128
|
-
Nodes can render text-based icons (emojis) or high-resolution images.
|
|
46
|
+
Instead of running costly CPU bounding-box calculations or iterating through arrays on every mouse movement:
|
|
129
47
|
|
|
130
|
-
|
|
131
|
-
engine.
|
|
132
|
-
id: "node-1",
|
|
133
|
-
icon: "📂", // Renders text/emoji in center
|
|
134
|
-
image: "url...", // Renders rounded image inside
|
|
135
|
-
size: 60
|
|
136
|
-
});
|
|
137
|
-
```
|
|
48
|
+
- VortxGL renders the entire scene to an offscreen buffer (Framebuffer Object) where each node is painted with a unique, color-coded RGB value mapping to its index.
|
|
49
|
+
- When clicking or hovering, the engine queries the exact pixel color under the mouse in $O(1)$ time, providing instantaneous selection feedback even on 100k+ elements.
|
|
138
50
|
|
|
139
|
-
###
|
|
140
|
-
Colors accept standard CSS hex strings or precision arrays for hardware-level control.
|
|
51
|
+
### 3. Multi-Threaded Layout Worker
|
|
141
52
|
|
|
142
|
-
|
|
143
|
-
// CSS Hex
|
|
144
|
-
color: "#ff4757"
|
|
53
|
+
Physics simulations and force layouts are mathematically heavy ($O(N^2)$ or $O(N \log N)$).
|
|
145
54
|
|
|
146
|
-
|
|
147
|
-
|
|
55
|
+
- VortxGL moves these physics computations entirely off the browser's main thread to a **background Web Worker**.
|
|
56
|
+
- The worker and main thread exchange coordinate data using **Transferable Objects** (`Float32Array` buffers). This allows memory ownership to be passed back and forth instantly with zero copy overhead, completely eliminating Garbage Collection frame drops.
|
|
148
57
|
|
|
149
|
-
|
|
150
|
-
color: [0, 0, 0, 0] // Useful for "ghost" nodes
|
|
151
|
-
```
|
|
58
|
+
### 4. Incremental Spatial Indexing
|
|
152
59
|
|
|
153
|
-
|
|
154
|
-
The engine supports built-in Dark and Light mode, affecting the background clear color and label contrast automatically.
|
|
60
|
+
To support spatial actions (like zoom-to-fit, group boundary calculations, and camera culling), VortxGL maintains an internal coordinate search index.
|
|
155
61
|
|
|
156
|
-
|
|
157
|
-
engine.setTheme("light"); // Switches to light background
|
|
158
|
-
```
|
|
62
|
+
- Rather than rebuilding the index on every single tick or position change (an $O(N)$ operation), the engine updates the spatial index incrementally in $O(1)$ time per node mutation.
|
|
159
63
|
|
|
160
|
-
|
|
64
|
+
### 5. Screen-Space Projection Caching
|
|
161
65
|
|
|
162
|
-
|
|
66
|
+
The engine projects world coordinates into screen coordinates to position overlay text. The projection calculations are cached in memory and marked dirty only when the Camera moves or Node positions change. This saves millions of redundant matrix-multiplication operations per second.
|
|
163
67
|
|
|
164
|
-
|
|
68
|
+
---
|
|
165
69
|
|
|
166
|
-
|
|
167
|
-
Groups are created by specifying a unique ID and a list of node IDs to include.
|
|
70
|
+
## 🚀 Key Features
|
|
168
71
|
|
|
169
|
-
|
|
170
|
-
engine.createGroup("group-alpha", "Engineers", ["node-1", "node-2", "node-3"]);
|
|
171
|
-
```
|
|
72
|
+
### 🎬 Energy Flow Animation
|
|
172
73
|
|
|
173
|
-
|
|
174
|
-
|
|
74
|
+
- Highlight data pathways (e.g. tracking transactions or packet routing) via hardware-accelerated particle flow along edges.
|
|
75
|
+
- Real-time controls for velocity, particle size, and opacity.
|
|
76
|
+
- Target flows dynamically by attributes (e.g. only animate edges matching `type === "transaction"`).
|
|
175
77
|
|
|
176
|
-
|
|
177
|
-
// Programmatically toggle state
|
|
178
|
-
engine.toggleComboCollapse("group-alpha");
|
|
78
|
+
### 📁 Collapsible Combos (Groups)
|
|
179
79
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
```
|
|
80
|
+
- Group nodes into logical cluster units.
|
|
81
|
+
- **Smart Hulls**: Automatically draws bounding convex hulls around expanded groups.
|
|
82
|
+
- **Smart Collapsing**: Collapses groups into single representative nodes, calculating the group centroid.
|
|
83
|
+
- **Cluster Translation**: Dragging a group moves all internal member nodes in sync.
|
|
185
84
|
|
|
186
|
-
###
|
|
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).
|
|
85
|
+
### ⛓️ Interactive Relation Builder
|
|
190
86
|
|
|
191
|
-
|
|
87
|
+
- Draw semantic relationships with drag-and-drop actions.
|
|
88
|
+
- **Phantom Edges**: Dashed preview line that tracks the mouse pointer during node-to-node connection.
|
|
89
|
+
- **On-the-fly Config**: Instantly modify connection weights, colors, and metadata before finalizing.
|
|
192
90
|
|
|
193
|
-
|
|
91
|
+
### 🎨 Cytoscape-Style Stylesheet System
|
|
194
92
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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 |
|
|
93
|
+
- Apply high-performance styling rules using class selectors (similar to CSS).
|
|
94
|
+
- Fallback hierarchies: Explicit properties > Classes > Theme Defaults.
|
|
95
|
+
- Built-in Dark and Light themes with automatic contrast shifts.
|
|
203
96
|
|
|
204
97
|
---
|
|
205
98
|
|
|
206
|
-
##
|
|
99
|
+
## 📦 Quick Start
|
|
207
100
|
|
|
208
|
-
|
|
101
|
+
### 1. Install
|
|
209
102
|
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
});
|
|
103
|
+
```bash
|
|
104
|
+
npm install vortx-gl
|
|
227
105
|
```
|
|
228
106
|
|
|
229
|
-
### 2.
|
|
230
|
-
You can configure the segments of the circular menu for nodes, edges, and combos through the engine instance.
|
|
107
|
+
### 2. Setup (Vue 3 Component)
|
|
231
108
|
|
|
232
|
-
|
|
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
|
-
```
|
|
109
|
+
Initialize the visualizer using the Vue 3 component. Simply provide a list of nodes and edges formatted with clean metadata.
|
|
239
110
|
|
|
240
|
-
|
|
241
|
-
|
|
111
|
+
```vue
|
|
112
|
+
<script setup lang="ts">
|
|
113
|
+
import { ref } from "vue";
|
|
114
|
+
import { GraphCanvas } from "vortx-gl";
|
|
115
|
+
import "vortx-gl/dist/vortx-gl.css";
|
|
242
116
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
117
|
+
const graphData = ref({
|
|
118
|
+
nodes: [
|
|
119
|
+
{
|
|
120
|
+
data: {
|
|
121
|
+
id: "node-1",
|
|
122
|
+
label: "Primary Database",
|
|
123
|
+
color: "#3178C6",
|
|
124
|
+
size: 60,
|
|
125
|
+
icon: "🖥️",
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
data: {
|
|
130
|
+
id: "node-2",
|
|
131
|
+
label: "API Gateway",
|
|
132
|
+
color: "#4FC08D",
|
|
133
|
+
size: 50,
|
|
134
|
+
icon: "🌐",
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
data: {
|
|
139
|
+
id: "node-3",
|
|
140
|
+
label: "Client App",
|
|
141
|
+
color: "#ff4757",
|
|
142
|
+
size: 40,
|
|
143
|
+
icon: "📱",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
edges: [
|
|
148
|
+
{
|
|
149
|
+
data: {
|
|
150
|
+
id: "edge-1",
|
|
151
|
+
source: "node-3",
|
|
152
|
+
target: "node-2",
|
|
153
|
+
label: "HTTPS Request",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
data: {
|
|
158
|
+
id: "edge-2",
|
|
159
|
+
source: "node-2",
|
|
160
|
+
target: "node-1",
|
|
161
|
+
label: "SQL Query",
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
],
|
|
251
165
|
});
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
### 4. Interactive Connection Workflow
|
|
166
|
+
</script>
|
|
255
167
|
|
|
256
|
-
|
|
168
|
+
<template>
|
|
169
|
+
<div class="canvas-container">
|
|
170
|
+
<GraphCanvas :data="graphData" />
|
|
171
|
+
</div>
|
|
172
|
+
</template>
|
|
257
173
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
174
|
+
<style scoped>
|
|
175
|
+
.canvas-container {
|
|
176
|
+
width: 100vw;
|
|
177
|
+
height: 100vh;
|
|
178
|
+
background-color: #0f172a;
|
|
179
|
+
}
|
|
180
|
+
</style>
|
|
181
|
+
```
|
|
262
182
|
|
|
263
183
|
---
|
|
264
184
|
|
|
185
|
+
## 🛠️ Developer API Examples
|
|
265
186
|
|
|
266
|
-
|
|
187
|
+
VortxGL provides an imperative, high-performance API for dynamic run-time adjustments.
|
|
267
188
|
|
|
268
|
-
|
|
189
|
+
### Add & Update Elements Programmatically
|
|
269
190
|
|
|
270
|
-
|
|
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
|
-
```
|
|
191
|
+
All layout and position updates are batch-uploaded directly to GPU buffers:
|
|
302
192
|
|
|
303
|
-
### 3. Removing Elements
|
|
304
193
|
```typescript
|
|
305
|
-
|
|
306
|
-
engine.removeNode("node-1");
|
|
194
|
+
import { GraphEngine } from "vortx-gl";
|
|
307
195
|
|
|
308
|
-
|
|
309
|
-
engine.removeEdge("edge-1");
|
|
196
|
+
const engine = new GraphEngine(canvasElement);
|
|
310
197
|
|
|
311
|
-
//
|
|
312
|
-
engine.
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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"
|
|
198
|
+
// Ingest a new node
|
|
199
|
+
engine.addNode({
|
|
200
|
+
id: "node-99",
|
|
201
|
+
label: "Microservice A",
|
|
202
|
+
position: { x: 150, y: -200 },
|
|
203
|
+
color: "#ff4757",
|
|
204
|
+
size: 55,
|
|
337
205
|
});
|
|
338
206
|
|
|
339
|
-
//
|
|
340
|
-
engine.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
label: "
|
|
344
|
-
data: {
|
|
345
|
-
customColor: "#ff00ff", // Override WebGL global color
|
|
346
|
-
customSize: 4.5 // Precise thickness in pixels
|
|
347
|
-
}
|
|
207
|
+
// Update node colors or sizes dynamically
|
|
208
|
+
engine.updateNode({
|
|
209
|
+
id: "node-99",
|
|
210
|
+
color: "#ffd2df",
|
|
211
|
+
label: "Microservice A (Dormant)",
|
|
348
212
|
});
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
---
|
|
352
|
-
|
|
353
|
-
## 🔍 Querying Elements
|
|
354
213
|
|
|
355
|
-
|
|
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();
|
|
214
|
+
// Delete elements (automatically cleans up connected edges and compacts the array buffers)
|
|
215
|
+
engine.removeNode("node-99");
|
|
378
216
|
```
|
|
379
217
|
|
|
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.
|
|
218
|
+
### Apply CSS-like Classes for Bulk Styling
|
|
388
219
|
|
|
389
220
|
```typescript
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
221
|
+
const stylesheet = {
|
|
222
|
+
database: { color: "#3178C6", size: 60, icon: "🗄️" },
|
|
223
|
+
gateway: { color: "#4FC08D", size: 50, icon: "🔌" },
|
|
224
|
+
unstable: { color: "#ff4757", size: 45, icon: "⚠️" },
|
|
394
225
|
};
|
|
395
226
|
|
|
396
|
-
engine.setStylesheet(
|
|
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.
|
|
227
|
+
engine.setStylesheet(stylesheet);
|
|
401
228
|
|
|
402
|
-
|
|
229
|
+
// Apply style via class names
|
|
403
230
|
engine.addNode({
|
|
404
|
-
id: "node
|
|
405
|
-
classes: ["
|
|
406
|
-
label: "
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
engine.addEdge({
|
|
410
|
-
source: "node-1",
|
|
411
|
-
target: "node-2",
|
|
412
|
-
classes: ["standard-link"]
|
|
231
|
+
id: "db-node",
|
|
232
|
+
classes: ["database", "unstable"],
|
|
233
|
+
label: "User DB",
|
|
413
234
|
});
|
|
414
235
|
```
|
|
415
236
|
|
|
416
|
-
###
|
|
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.
|
|
237
|
+
### Triggering Layouts (Circle, Grid, Force-Directed)
|
|
421
238
|
|
|
422
|
-
|
|
239
|
+
Layout math runs completely inside the Web Worker thread:
|
|
423
240
|
|
|
424
|
-
|
|
241
|
+
```typescript
|
|
242
|
+
// Circular layout
|
|
243
|
+
engine.runLayout("circle");
|
|
425
244
|
|
|
426
|
-
|
|
245
|
+
// Concentric layout with custom spacings
|
|
246
|
+
engine.runLayout("concentric", { spacing: 2 });
|
|
427
247
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
engine.setFlowConfig({
|
|
431
|
-
enabled: true,
|
|
432
|
-
velocity: 0.005,
|
|
433
|
-
size: 2,
|
|
434
|
-
color: "#00ffcc"
|
|
435
|
-
});
|
|
248
|
+
// Run layout exclusively on selected nodes
|
|
249
|
+
engine.runLayout("grid", { selectedOnly: true });
|
|
436
250
|
```
|
|
437
251
|
|
|
438
|
-
###
|
|
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.
|
|
252
|
+
### Animating Edge Particle Flows
|
|
440
253
|
|
|
441
254
|
```typescript
|
|
442
255
|
engine.setFlowConfig({
|
|
443
256
|
enabled: true,
|
|
444
|
-
|
|
257
|
+
velocity: 0.004, // Particle movement speed
|
|
258
|
+
size: 2.5, // Particle radius in pixels
|
|
259
|
+
color: "#ffd32a", // Glowing yellow particle streams
|
|
445
260
|
});
|
|
446
261
|
```
|
|
447
262
|
|
|
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
263
|
---
|
|
459
264
|
|
|
460
|
-
##
|
|
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
|
-
```
|
|
265
|
+
## ⌨️ Shortcuts & Interaction HUD
|
|
476
266
|
|
|
477
|
-
|
|
478
|
-
|
|
|
479
|
-
|
|
|
480
|
-
| **
|
|
481
|
-
| **
|
|
482
|
-
| **
|
|
483
|
-
| **
|
|
484
|
-
| **
|
|
267
|
+
| Control | Action | Description |
|
|
268
|
+
| :--------------------- | :--------- | :---------------------------------------------- |
|
|
269
|
+
| **Left-Click** | Select | Selects nodes, edges, or group hulls |
|
|
270
|
+
| **Left-Drag** | Pan | Drags the viewport camera |
|
|
271
|
+
| **Scroll Wheel** | Zoom | Zooms in/out centered at mouse pointer |
|
|
272
|
+
| **Shift + Drag** | Box Select | Selects multiple nodes via selection marquee |
|
|
273
|
+
| **Radial Right-Click** | Menu | Opens dynamic, context-aware command HUD |
|
|
274
|
+
| **F** Key | Frame Fit | Instantly center and snap viewport to fit graph |
|
|
485
275
|
|
|
486
276
|
---
|
|
487
277
|
|
|
488
|
-
##
|
|
489
|
-
|
|
490
|
-
Control the view programmatically to create cinematic transitions or automated "focus" actions.
|
|
278
|
+
## 🧬 Event Hooks
|
|
491
279
|
|
|
492
|
-
|
|
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
|
-
```
|
|
280
|
+
VortxGL features an event listener pipeline for building interactive dashboards:
|
|
500
281
|
|
|
501
|
-
### 2. Zoom Controls
|
|
502
282
|
```typescript
|
|
503
|
-
|
|
504
|
-
engine.
|
|
505
|
-
|
|
506
|
-
|
|
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.
|
|
283
|
+
// Subscribe to clicks
|
|
284
|
+
const unsubscribe = engine.on("node:click", ({ id }) => {
|
|
285
|
+
console.log(`User selected node ID: ${id}`);
|
|
286
|
+
});
|
|
542
287
|
|
|
543
|
-
|
|
544
|
-
|
|
288
|
+
// Unsubscribe during clean up
|
|
289
|
+
unsubscribe();
|
|
545
290
|
```
|
|
546
291
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
292
|
+
| Event Key | Trigger Condition |
|
|
293
|
+
| :---------------------------- | :--------------------------------------------------- |
|
|
294
|
+
| `node:click` / `node:hover` | Interacting with a node |
|
|
295
|
+
| `edge:click` / `edge:hover` | Interacting with an edge |
|
|
296
|
+
| `combo:click` / `combo:hover` | Interacting with a group hull or representative node |
|
|
297
|
+
| `graph:click` | Clicking empty space on the canvas |
|
|
298
|
+
| `graph:pan` / `graph:zoom` | Moving the camera viewport |
|
|
299
|
+
| `boxstart` / `boxend` | Triggering or ending marquee selection |
|
|
555
300
|
|
|
556
301
|
---
|
|
557
302
|
|
|
558
303
|
## 📜 License
|
|
559
304
|
|
|
560
|
-
|
|
305
|
+
VortxGL is distributed under the Apache License 2.0. See the [LICENSE](LICENSE) file for complete details.
|