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 +485 -35
- package/dist/engine/events.d.ts +32 -0
- package/dist/engine/interaction.d.ts +26 -0
- package/dist/engine/overlay.d.ts +80 -0
- package/dist/engine/picking.d.ts +40 -0
- package/dist/engine/renderer.d.ts +469 -0
- package/dist/engine/shaders.d.ts +4 -0
- package/dist/engine/types.d.ts +225 -0
- package/dist/index.d.ts +8 -1
- package/dist/vortx-gl.css +1 -1
- package/dist/vortx-gl.es.js +1 -1
- package/dist/vortx-gl.umd.js +1 -1
- package/examples/vue-example.vue +24 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
# VortxGL 🎨
|
|
2
2
|
|
|
3
|
-
A high-performance
|
|
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: "#
|
|
29
|
-
backgroundImage: "https://example.com/icon.png",
|
|
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
|
-
🚀 **
|
|
87
|
+
🚀 **Experience the Speed**: [View the Live Demo](https://webgl-graph.vercel.app)
|
|
49
88
|
|
|
50
89
|
---
|
|
51
90
|
|
|
52
|
-
##
|
|
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
|
-
|
|
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": "
|
|
73
|
-
"color": "#
|
|
74
|
-
"
|
|
75
|
-
"
|
|
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": "
|
|
84
|
-
"source": "1",
|
|
85
|
-
"target": "2",
|
|
86
|
-
"label": "
|
|
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
|
-
##
|
|
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
|
|
101
|
-
| **Scroll** | Zoom at mouse
|
|
102
|
-
| **Shift + Drag** | Box Selection
|
|
103
|
-
| **Right Click**
|
|
104
|
-
| **F** |
|
|
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
|
+
}
|