force-3d-graph 1.2.1 → 1.2.3
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/dist/force-3d-graph.js +420 -420
- package/dist/force-3d-graph.js.map +1 -1
- package/dist/force-3d-graph.umd.cjs +19 -19
- package/dist/force-3d-graph.umd.cjs.map +1 -1
- package/package.json +1 -1
package/dist/force-3d-graph.js
CHANGED
|
@@ -92,14 +92,14 @@ class gt extends ot {
|
|
|
92
92
|
}, this.saveState = function() {
|
|
93
93
|
t.target0.copy(t.target), t.position0.copy(t.object.position), t.zoom0 = t.object.zoom;
|
|
94
94
|
}, this.reset = function() {
|
|
95
|
-
t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(ke), t.update(),
|
|
95
|
+
t.target.copy(t.target0), t.object.position.copy(t.position0), t.object.zoom = t.zoom0, t.object.updateProjectionMatrix(), t.dispatchEvent(ke), t.update(), o = i.NONE;
|
|
96
96
|
}, this.update = function() {
|
|
97
|
-
const n = new S(),
|
|
97
|
+
const n = new S(), g = new Se().setFromUnitVectors(e.up, new S(0, 1, 0)), v = g.clone().invert(), w = new S(), C = new Se(), F = new S(), z = 2 * Math.PI;
|
|
98
98
|
return function(tt = null) {
|
|
99
99
|
const Ce = t.object.position;
|
|
100
|
-
n.copy(Ce).sub(t.target), n.applyQuaternion(
|
|
100
|
+
n.copy(Ce).sub(t.target), n.applyQuaternion(g), r.setFromVector3(n), t.autoRotate && o === i.NONE && B(He(tt)), t.enableDamping ? (r.theta += c.theta * t.dampingFactor, r.phi += c.phi * t.dampingFactor) : (r.theta += c.theta, r.phi += c.phi);
|
|
101
101
|
let I = t.minAzimuthAngle, R = t.maxAzimuthAngle;
|
|
102
|
-
isFinite(I) && isFinite(R) && (I < -Math.PI ? I += z : I > Math.PI && (I -= z), R < -Math.PI ? R += z : R > Math.PI && (R -= z), I <= R ? r.theta = Math.max(I, Math.min(R, r.theta)) : r.theta = r.theta > (I + R) / 2 ? Math.max(I, r.theta) : Math.min(R, r.theta)), r.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, r.phi)), r.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(
|
|
102
|
+
isFinite(I) && isFinite(R) && (I < -Math.PI ? I += z : I > Math.PI && (I -= z), R < -Math.PI ? R += z : R > Math.PI && (R -= z), I <= R ? r.theta = Math.max(I, Math.min(R, r.theta)) : r.theta = r.theta > (I + R) / 2 ? Math.max(I, r.theta) : Math.min(R, r.theta)), r.phi = Math.max(t.minPolarAngle, Math.min(t.maxPolarAngle, r.phi)), r.makeSafe(), t.enableDamping === !0 ? t.target.addScaledVector(p, t.dampingFactor) : t.target.add(p), t.target.sub(t.cursor), t.target.clampLength(t.minTargetRadius, t.maxTargetRadius), t.target.add(t.cursor), t.zoomToCursor && H || t.object.isOrthographicCamera ? r.radius = ie(r.radius) : r.radius = ie(r.radius * d), n.setFromSpherical(r), n.applyQuaternion(v), Ce.copy(t.target).add(n), t.object.lookAt(t.target), t.enableDamping === !0 ? (c.theta *= 1 - t.dampingFactor, c.phi *= 1 - t.dampingFactor, p.multiplyScalar(1 - t.dampingFactor)) : (c.set(0, 0, 0), p.set(0, 0, 0));
|
|
103
103
|
let ae = !1;
|
|
104
104
|
if (t.zoomToCursor && H) {
|
|
105
105
|
let X = null;
|
|
@@ -122,7 +122,7 @@ class gt extends ot {
|
|
|
122
122
|
}(), this.dispose = function() {
|
|
123
123
|
t.domElement.removeEventListener("contextmenu", we), t.domElement.removeEventListener("pointerdown", be), t.domElement.removeEventListener("pointercancel", K), t.domElement.removeEventListener("wheel", ve), t.domElement.removeEventListener("pointermove", oe), t.domElement.removeEventListener("pointerup", K), t._domElementKeyEvents !== null && (t._domElementKeyEvents.removeEventListener("keydown", ne), t._domElementKeyEvents = null);
|
|
124
124
|
};
|
|
125
|
-
const t = this,
|
|
125
|
+
const t = this, i = {
|
|
126
126
|
NONE: -1,
|
|
127
127
|
ROTATE: 0,
|
|
128
128
|
DOLLY: 1,
|
|
@@ -132,10 +132,10 @@ class gt extends ot {
|
|
|
132
132
|
TOUCH_DOLLY_PAN: 5,
|
|
133
133
|
TOUCH_DOLLY_ROTATE: 6
|
|
134
134
|
};
|
|
135
|
-
let
|
|
135
|
+
let o = i.NONE;
|
|
136
136
|
const a = 1e-6, r = new Ne(), c = new Ne();
|
|
137
137
|
let d = 1;
|
|
138
|
-
const
|
|
138
|
+
const p = new S(), x = new k(), f = new k(), u = new k(), y = new k(), b = new k(), M = new k(), N = new k(), O = new k(), L = new k(), Y = new S(), P = new k();
|
|
139
139
|
let H = !1;
|
|
140
140
|
const E = [], _ = {};
|
|
141
141
|
let ee = !1;
|
|
@@ -143,8 +143,8 @@ class gt extends ot {
|
|
|
143
143
|
return n !== null ? 2 * Math.PI / 60 * t.autoRotateSpeed * n : 2 * Math.PI / 60 / 60 * t.autoRotateSpeed;
|
|
144
144
|
}
|
|
145
145
|
function q(n) {
|
|
146
|
-
const
|
|
147
|
-
return Math.pow(0.95, t.zoomSpeed *
|
|
146
|
+
const g = Math.abs(n * 0.01);
|
|
147
|
+
return Math.pow(0.95, t.zoomSpeed * g);
|
|
148
148
|
}
|
|
149
149
|
function B(n) {
|
|
150
150
|
c.theta -= n;
|
|
@@ -154,24 +154,24 @@ class gt extends ot {
|
|
|
154
154
|
}
|
|
155
155
|
const le = function() {
|
|
156
156
|
const n = new S();
|
|
157
|
-
return function(
|
|
158
|
-
n.setFromMatrixColumn(w, 0), n.multiplyScalar(-
|
|
157
|
+
return function(v, w) {
|
|
158
|
+
n.setFromMatrixColumn(w, 0), n.multiplyScalar(-v), p.add(n);
|
|
159
159
|
};
|
|
160
160
|
}(), ce = function() {
|
|
161
161
|
const n = new S();
|
|
162
|
-
return function(
|
|
163
|
-
t.screenSpacePanning === !0 ? n.setFromMatrixColumn(w, 1) : (n.setFromMatrixColumn(w, 0), n.crossVectors(t.object.up, n)), n.multiplyScalar(
|
|
162
|
+
return function(v, w) {
|
|
163
|
+
t.screenSpacePanning === !0 ? n.setFromMatrixColumn(w, 1) : (n.setFromMatrixColumn(w, 0), n.crossVectors(t.object.up, n)), n.multiplyScalar(v), p.add(n);
|
|
164
164
|
};
|
|
165
165
|
}(), A = function() {
|
|
166
166
|
const n = new S();
|
|
167
|
-
return function(
|
|
167
|
+
return function(v, w) {
|
|
168
168
|
const C = t.domElement;
|
|
169
169
|
if (t.object.isPerspectiveCamera) {
|
|
170
170
|
const F = t.object.position;
|
|
171
171
|
n.copy(F).sub(t.target);
|
|
172
172
|
let z = n.length();
|
|
173
|
-
z *= Math.tan(t.object.fov / 2 * Math.PI / 180), le(2 *
|
|
174
|
-
} else t.object.isOrthographicCamera ? (le(
|
|
173
|
+
z *= Math.tan(t.object.fov / 2 * Math.PI / 180), le(2 * v * z / C.clientHeight, t.object.matrix), ce(2 * w * z / C.clientHeight, t.object.matrix);
|
|
174
|
+
} else t.object.isOrthographicCamera ? (le(v * (t.object.right - t.object.left) / t.object.zoom / C.clientWidth, t.object.matrix), ce(w * (t.object.top - t.object.bottom) / t.object.zoom / C.clientHeight, t.object.matrix)) : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."), t.enablePan = !1);
|
|
175
175
|
};
|
|
176
176
|
}();
|
|
177
177
|
function te(n) {
|
|
@@ -180,75 +180,75 @@ class gt extends ot {
|
|
|
180
180
|
function he(n) {
|
|
181
181
|
t.object.isPerspectiveCamera || t.object.isOrthographicCamera ? d *= n : (console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."), t.enableZoom = !1);
|
|
182
182
|
}
|
|
183
|
-
function se(n,
|
|
183
|
+
function se(n, g) {
|
|
184
184
|
if (!t.zoomToCursor)
|
|
185
185
|
return;
|
|
186
186
|
H = !0;
|
|
187
|
-
const
|
|
187
|
+
const v = t.domElement.getBoundingClientRect(), w = n - v.left, C = g - v.top, F = v.width, z = v.height;
|
|
188
188
|
P.x = w / F * 2 - 1, P.y = -(C / z) * 2 + 1, Y.set(P.x, P.y, 1).unproject(t.object).sub(t.object.position).normalize();
|
|
189
189
|
}
|
|
190
190
|
function ie(n) {
|
|
191
191
|
return Math.max(t.minDistance, Math.min(t.maxDistance, n));
|
|
192
192
|
}
|
|
193
193
|
function de(n) {
|
|
194
|
-
|
|
194
|
+
x.set(n.clientX, n.clientY);
|
|
195
195
|
}
|
|
196
196
|
function De(n) {
|
|
197
197
|
se(n.clientX, n.clientX), N.set(n.clientX, n.clientY);
|
|
198
198
|
}
|
|
199
199
|
function pe(n) {
|
|
200
|
-
|
|
200
|
+
y.set(n.clientX, n.clientY);
|
|
201
201
|
}
|
|
202
202
|
function Ae(n) {
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
B(2 * Math.PI *
|
|
203
|
+
f.set(n.clientX, n.clientY), u.subVectors(f, x).multiplyScalar(t.rotateSpeed);
|
|
204
|
+
const g = t.domElement;
|
|
205
|
+
B(2 * Math.PI * u.x / g.clientHeight), W(2 * Math.PI * u.y / g.clientHeight), x.copy(f), t.update();
|
|
206
206
|
}
|
|
207
207
|
function je(n) {
|
|
208
208
|
O.set(n.clientX, n.clientY), L.subVectors(O, N), L.y > 0 ? te(q(L.y)) : L.y < 0 && he(q(L.y)), N.copy(O), t.update();
|
|
209
209
|
}
|
|
210
210
|
function $e(n) {
|
|
211
|
-
|
|
211
|
+
b.set(n.clientX, n.clientY), M.subVectors(b, y).multiplyScalar(t.panSpeed), A(M.x, M.y), y.copy(b), t.update();
|
|
212
212
|
}
|
|
213
213
|
function Ge(n) {
|
|
214
214
|
se(n.clientX, n.clientY), n.deltaY < 0 ? he(q(n.deltaY)) : n.deltaY > 0 && te(q(n.deltaY)), t.update();
|
|
215
215
|
}
|
|
216
216
|
function Ye(n) {
|
|
217
|
-
let
|
|
217
|
+
let g = !1;
|
|
218
218
|
switch (n.code) {
|
|
219
219
|
case t.keys.UP:
|
|
220
|
-
n.ctrlKey || n.metaKey || n.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, t.keyPanSpeed),
|
|
220
|
+
n.ctrlKey || n.metaKey || n.shiftKey ? W(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, t.keyPanSpeed), g = !0;
|
|
221
221
|
break;
|
|
222
222
|
case t.keys.BOTTOM:
|
|
223
|
-
n.ctrlKey || n.metaKey || n.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, -t.keyPanSpeed),
|
|
223
|
+
n.ctrlKey || n.metaKey || n.shiftKey ? W(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(0, -t.keyPanSpeed), g = !0;
|
|
224
224
|
break;
|
|
225
225
|
case t.keys.LEFT:
|
|
226
|
-
n.ctrlKey || n.metaKey || n.shiftKey ? B(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(t.keyPanSpeed, 0),
|
|
226
|
+
n.ctrlKey || n.metaKey || n.shiftKey ? B(2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(t.keyPanSpeed, 0), g = !0;
|
|
227
227
|
break;
|
|
228
228
|
case t.keys.RIGHT:
|
|
229
|
-
n.ctrlKey || n.metaKey || n.shiftKey ? B(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(-t.keyPanSpeed, 0),
|
|
229
|
+
n.ctrlKey || n.metaKey || n.shiftKey ? B(-2 * Math.PI * t.rotateSpeed / t.domElement.clientHeight) : A(-t.keyPanSpeed, 0), g = !0;
|
|
230
230
|
break;
|
|
231
231
|
}
|
|
232
|
-
|
|
232
|
+
g && (n.preventDefault(), t.update());
|
|
233
233
|
}
|
|
234
234
|
function ge(n) {
|
|
235
235
|
if (E.length === 1)
|
|
236
|
-
|
|
236
|
+
x.set(n.pageX, n.pageY);
|
|
237
237
|
else {
|
|
238
|
-
const
|
|
239
|
-
|
|
238
|
+
const g = j(n), v = 0.5 * (n.pageX + g.x), w = 0.5 * (n.pageY + g.y);
|
|
239
|
+
x.set(v, w);
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
function ue(n) {
|
|
243
243
|
if (E.length === 1)
|
|
244
|
-
|
|
244
|
+
y.set(n.pageX, n.pageY);
|
|
245
245
|
else {
|
|
246
|
-
const
|
|
247
|
-
|
|
246
|
+
const g = j(n), v = 0.5 * (n.pageX + g.x), w = 0.5 * (n.pageY + g.y);
|
|
247
|
+
y.set(v, w);
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
function fe(n) {
|
|
251
|
-
const
|
|
251
|
+
const g = j(n), v = n.pageX - g.x, w = n.pageY - g.y, C = Math.sqrt(v * v + w * w);
|
|
252
252
|
N.set(0, C);
|
|
253
253
|
}
|
|
254
254
|
function Be(n) {
|
|
@@ -259,28 +259,28 @@ class gt extends ot {
|
|
|
259
259
|
}
|
|
260
260
|
function me(n) {
|
|
261
261
|
if (E.length == 1)
|
|
262
|
-
|
|
262
|
+
f.set(n.pageX, n.pageY);
|
|
263
263
|
else {
|
|
264
|
-
const
|
|
265
|
-
|
|
264
|
+
const v = j(n), w = 0.5 * (n.pageX + v.x), C = 0.5 * (n.pageY + v.y);
|
|
265
|
+
f.set(w, C);
|
|
266
266
|
}
|
|
267
|
-
|
|
268
|
-
const
|
|
269
|
-
B(2 * Math.PI *
|
|
267
|
+
u.subVectors(f, x).multiplyScalar(t.rotateSpeed);
|
|
268
|
+
const g = t.domElement;
|
|
269
|
+
B(2 * Math.PI * u.x / g.clientHeight), W(2 * Math.PI * u.y / g.clientHeight), x.copy(f);
|
|
270
270
|
}
|
|
271
271
|
function ye(n) {
|
|
272
272
|
if (E.length === 1)
|
|
273
|
-
|
|
273
|
+
b.set(n.pageX, n.pageY);
|
|
274
274
|
else {
|
|
275
|
-
const
|
|
276
|
-
|
|
275
|
+
const g = j(n), v = 0.5 * (n.pageX + g.x), w = 0.5 * (n.pageY + g.y);
|
|
276
|
+
b.set(v, w);
|
|
277
277
|
}
|
|
278
|
-
M.subVectors(
|
|
278
|
+
M.subVectors(b, y).multiplyScalar(t.panSpeed), A(M.x, M.y), y.copy(b);
|
|
279
279
|
}
|
|
280
280
|
function xe(n) {
|
|
281
|
-
const
|
|
281
|
+
const g = j(n), v = n.pageX - g.x, w = n.pageY - g.y, C = Math.sqrt(v * v + w * w);
|
|
282
282
|
O.set(0, C), L.set(0, Math.pow(O.y / N.y, t.zoomSpeed)), te(L.y), N.copy(O);
|
|
283
|
-
const F = (n.pageX +
|
|
283
|
+
const F = (n.pageX + g.x) * 0.5, z = (n.pageY + g.y) * 0.5;
|
|
284
284
|
se(F, z);
|
|
285
285
|
}
|
|
286
286
|
function Xe(n) {
|
|
@@ -296,85 +296,85 @@ class gt extends ot {
|
|
|
296
296
|
t.enabled !== !1 && (n.pointerType === "touch" ? Qe(n) : _e(n));
|
|
297
297
|
}
|
|
298
298
|
function K(n) {
|
|
299
|
-
et(n), E.length === 0 && (t.domElement.releasePointerCapture(n.pointerId), t.domElement.removeEventListener("pointermove", oe), t.domElement.removeEventListener("pointerup", K)), t.dispatchEvent(Pe),
|
|
299
|
+
et(n), E.length === 0 && (t.domElement.releasePointerCapture(n.pointerId), t.domElement.removeEventListener("pointermove", oe), t.domElement.removeEventListener("pointerup", K)), t.dispatchEvent(Pe), o = i.NONE;
|
|
300
300
|
}
|
|
301
301
|
function Ue(n) {
|
|
302
|
-
let
|
|
302
|
+
let g;
|
|
303
303
|
switch (n.button) {
|
|
304
304
|
case 0:
|
|
305
|
-
|
|
305
|
+
g = t.mouseButtons.LEFT;
|
|
306
306
|
break;
|
|
307
307
|
case 1:
|
|
308
|
-
|
|
308
|
+
g = t.mouseButtons.MIDDLE;
|
|
309
309
|
break;
|
|
310
310
|
case 2:
|
|
311
|
-
|
|
311
|
+
g = t.mouseButtons.RIGHT;
|
|
312
312
|
break;
|
|
313
313
|
default:
|
|
314
|
-
|
|
314
|
+
g = -1;
|
|
315
315
|
}
|
|
316
|
-
switch (
|
|
316
|
+
switch (g) {
|
|
317
317
|
case $.DOLLY:
|
|
318
318
|
if (t.enableZoom === !1) return;
|
|
319
|
-
De(n),
|
|
319
|
+
De(n), o = i.DOLLY;
|
|
320
320
|
break;
|
|
321
321
|
case $.ROTATE:
|
|
322
322
|
if (n.ctrlKey || n.metaKey || n.shiftKey) {
|
|
323
323
|
if (t.enablePan === !1) return;
|
|
324
|
-
pe(n),
|
|
324
|
+
pe(n), o = i.PAN;
|
|
325
325
|
} else {
|
|
326
326
|
if (t.enableRotate === !1) return;
|
|
327
|
-
de(n),
|
|
327
|
+
de(n), o = i.ROTATE;
|
|
328
328
|
}
|
|
329
329
|
break;
|
|
330
330
|
case $.PAN:
|
|
331
331
|
if (n.ctrlKey || n.metaKey || n.shiftKey) {
|
|
332
332
|
if (t.enableRotate === !1) return;
|
|
333
|
-
de(n),
|
|
333
|
+
de(n), o = i.ROTATE;
|
|
334
334
|
} else {
|
|
335
335
|
if (t.enablePan === !1) return;
|
|
336
|
-
pe(n),
|
|
336
|
+
pe(n), o = i.PAN;
|
|
337
337
|
}
|
|
338
338
|
break;
|
|
339
339
|
default:
|
|
340
|
-
|
|
340
|
+
o = i.NONE;
|
|
341
341
|
}
|
|
342
|
-
|
|
342
|
+
o !== i.NONE && t.dispatchEvent(re);
|
|
343
343
|
}
|
|
344
344
|
function _e(n) {
|
|
345
|
-
switch (
|
|
346
|
-
case
|
|
345
|
+
switch (o) {
|
|
346
|
+
case i.ROTATE:
|
|
347
347
|
if (t.enableRotate === !1) return;
|
|
348
348
|
Ae(n);
|
|
349
349
|
break;
|
|
350
|
-
case
|
|
350
|
+
case i.DOLLY:
|
|
351
351
|
if (t.enableZoom === !1) return;
|
|
352
352
|
je(n);
|
|
353
353
|
break;
|
|
354
|
-
case
|
|
354
|
+
case i.PAN:
|
|
355
355
|
if (t.enablePan === !1) return;
|
|
356
356
|
$e(n);
|
|
357
357
|
break;
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
360
|
function ve(n) {
|
|
361
|
-
t.enabled === !1 || t.enableZoom === !1 ||
|
|
361
|
+
t.enabled === !1 || t.enableZoom === !1 || o !== i.NONE || (n.preventDefault(), t.dispatchEvent(re), Ge(qe(n)), t.dispatchEvent(Pe));
|
|
362
362
|
}
|
|
363
363
|
function qe(n) {
|
|
364
|
-
const
|
|
364
|
+
const g = n.deltaMode, v = {
|
|
365
365
|
clientX: n.clientX,
|
|
366
366
|
clientY: n.clientY,
|
|
367
367
|
deltaY: n.deltaY
|
|
368
368
|
};
|
|
369
|
-
switch (
|
|
369
|
+
switch (g) {
|
|
370
370
|
case 1:
|
|
371
|
-
|
|
371
|
+
v.deltaY *= 16;
|
|
372
372
|
break;
|
|
373
373
|
case 2:
|
|
374
|
-
|
|
374
|
+
v.deltaY *= 100;
|
|
375
375
|
break;
|
|
376
376
|
}
|
|
377
|
-
return n.ctrlKey && !ee && (
|
|
377
|
+
return n.ctrlKey && !ee && (v.deltaY *= 10), v;
|
|
378
378
|
}
|
|
379
379
|
function We(n) {
|
|
380
380
|
n.key === "Control" && (ee = !0, document.addEventListener("keyup", Me, { passive: !0, capture: !0 }));
|
|
@@ -391,55 +391,55 @@ class gt extends ot {
|
|
|
391
391
|
switch (t.touches.ONE) {
|
|
392
392
|
case G.ROTATE:
|
|
393
393
|
if (t.enableRotate === !1) return;
|
|
394
|
-
ge(n),
|
|
394
|
+
ge(n), o = i.TOUCH_ROTATE;
|
|
395
395
|
break;
|
|
396
396
|
case G.PAN:
|
|
397
397
|
if (t.enablePan === !1) return;
|
|
398
|
-
ue(n),
|
|
398
|
+
ue(n), o = i.TOUCH_PAN;
|
|
399
399
|
break;
|
|
400
400
|
default:
|
|
401
|
-
|
|
401
|
+
o = i.NONE;
|
|
402
402
|
}
|
|
403
403
|
break;
|
|
404
404
|
case 2:
|
|
405
405
|
switch (t.touches.TWO) {
|
|
406
406
|
case G.DOLLY_PAN:
|
|
407
407
|
if (t.enableZoom === !1 && t.enablePan === !1) return;
|
|
408
|
-
Be(n),
|
|
408
|
+
Be(n), o = i.TOUCH_DOLLY_PAN;
|
|
409
409
|
break;
|
|
410
410
|
case G.DOLLY_ROTATE:
|
|
411
411
|
if (t.enableZoom === !1 && t.enableRotate === !1) return;
|
|
412
|
-
Ke(n),
|
|
412
|
+
Ke(n), o = i.TOUCH_DOLLY_ROTATE;
|
|
413
413
|
break;
|
|
414
414
|
default:
|
|
415
|
-
|
|
415
|
+
o = i.NONE;
|
|
416
416
|
}
|
|
417
417
|
break;
|
|
418
418
|
default:
|
|
419
|
-
|
|
419
|
+
o = i.NONE;
|
|
420
420
|
}
|
|
421
|
-
|
|
421
|
+
o !== i.NONE && t.dispatchEvent(re);
|
|
422
422
|
}
|
|
423
423
|
function Qe(n) {
|
|
424
|
-
switch (Ee(n),
|
|
425
|
-
case
|
|
424
|
+
switch (Ee(n), o) {
|
|
425
|
+
case i.TOUCH_ROTATE:
|
|
426
426
|
if (t.enableRotate === !1) return;
|
|
427
427
|
me(n), t.update();
|
|
428
428
|
break;
|
|
429
|
-
case
|
|
429
|
+
case i.TOUCH_PAN:
|
|
430
430
|
if (t.enablePan === !1) return;
|
|
431
431
|
ye(n), t.update();
|
|
432
432
|
break;
|
|
433
|
-
case
|
|
433
|
+
case i.TOUCH_DOLLY_PAN:
|
|
434
434
|
if (t.enableZoom === !1 && t.enablePan === !1) return;
|
|
435
435
|
Xe(n), t.update();
|
|
436
436
|
break;
|
|
437
|
-
case
|
|
437
|
+
case i.TOUCH_DOLLY_ROTATE:
|
|
438
438
|
if (t.enableZoom === !1 && t.enableRotate === !1) return;
|
|
439
439
|
Ve(n), t.update();
|
|
440
440
|
break;
|
|
441
441
|
default:
|
|
442
|
-
|
|
442
|
+
o = i.NONE;
|
|
443
443
|
}
|
|
444
444
|
}
|
|
445
445
|
function we(n) {
|
|
@@ -450,19 +450,19 @@ class gt extends ot {
|
|
|
450
450
|
}
|
|
451
451
|
function et(n) {
|
|
452
452
|
delete _[n.pointerId];
|
|
453
|
-
for (let
|
|
454
|
-
if (E[
|
|
455
|
-
E.splice(
|
|
453
|
+
for (let g = 0; g < E.length; g++)
|
|
454
|
+
if (E[g] == n.pointerId) {
|
|
455
|
+
E.splice(g, 1);
|
|
456
456
|
return;
|
|
457
457
|
}
|
|
458
458
|
}
|
|
459
459
|
function Ee(n) {
|
|
460
|
-
let
|
|
461
|
-
|
|
460
|
+
let g = _[n.pointerId];
|
|
461
|
+
g === void 0 && (g = new k(), _[n.pointerId] = g), g.set(n.pageX, n.pageY);
|
|
462
462
|
}
|
|
463
463
|
function j(n) {
|
|
464
|
-
const
|
|
465
|
-
return _[
|
|
464
|
+
const g = n.pointerId === E[0] ? E[1] : E[0];
|
|
465
|
+
return _[g];
|
|
466
466
|
}
|
|
467
467
|
t.domElement.addEventListener("contextmenu", we), t.domElement.addEventListener("pointerdown", be), t.domElement.addEventListener("pointercancel", K), t.domElement.addEventListener("wheel", ve, { passive: !1 }), document.addEventListener("keydown", We, { passive: !0, capture: !0 }), this.update();
|
|
468
468
|
}
|
|
@@ -478,14 +478,14 @@ class ut {
|
|
|
478
478
|
this.container = e, this.scene = new m.Scene(), this.scene.background = new m.Color(
|
|
479
479
|
s.backgroundColor ?? 657930
|
|
480
480
|
);
|
|
481
|
-
const { width: t, height:
|
|
482
|
-
this.camera = new m.PerspectiveCamera(
|
|
481
|
+
const { width: t, height: i } = ze(e), o = s.cameraFov ?? 75;
|
|
482
|
+
this.camera = new m.PerspectiveCamera(o, t / i, 0.1, 2e3);
|
|
483
483
|
const a = s.cameraPosition ?? { x: 0, y: 0, z: 80 };
|
|
484
484
|
this.camera.position.set(a.x, a.y, a.z), this.renderer = new m.WebGLRenderer({
|
|
485
485
|
antialias: !0,
|
|
486
486
|
alpha: !0,
|
|
487
487
|
powerPreference: "high-performance"
|
|
488
|
-
}), this.renderer.setSize(t,
|
|
488
|
+
}), this.renderer.setSize(t, i), this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)), this.renderer.toneMapping = m.ACESFilmicToneMapping, this.renderer.toneMappingExposure = 1, this.renderer.shadowMap.enabled = !0, this.renderer.shadowMap.type = m.PCFSoftShadowMap, e.appendChild(this.renderer.domElement), this.controls = new gt(this.camera, this.renderer.domElement), this.controls.enableDamping = !0, this.controls.dampingFactor = 0.05, this.controls.rotateSpeed = 0.8, this.controls.zoomSpeed = 1.2, this.controls.minDistance = 10, this.controls.maxDistance = 500, this.setupLighting(), this.resizeHandler = this.onWindowResize.bind(this), window.addEventListener("resize", this.resizeHandler);
|
|
489
489
|
}
|
|
490
490
|
/**
|
|
491
491
|
* Sets up scene lighting for gradient glass on dark background
|
|
@@ -497,10 +497,10 @@ class ut {
|
|
|
497
497
|
s.position.set(50, 60, 40), s.castShadow = !0, s.shadow.mapSize.width = 1024, s.shadow.mapSize.height = 1024, this.scene.add(s);
|
|
498
498
|
const t = new m.DirectionalLight(16773344, 0.4);
|
|
499
499
|
t.position.set(-50, 30, -40), this.scene.add(t);
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
const
|
|
503
|
-
|
|
500
|
+
const i = new m.DirectionalLight(16777215, 0.3);
|
|
501
|
+
i.position.set(0, -30, -50), this.scene.add(i);
|
|
502
|
+
const o = new m.PointLight(16750950, 0.5, 150);
|
|
503
|
+
o.position.set(40, 20, 40), this.scene.add(o);
|
|
504
504
|
const a = new m.PointLight(16764057, 0.4, 150);
|
|
505
505
|
a.position.set(-40, -20, 40), this.scene.add(a);
|
|
506
506
|
const r = new m.PointLight(6724095, 0.2, 100);
|
|
@@ -585,16 +585,16 @@ class ft {
|
|
|
585
585
|
x: (Math.random() - 0.5) * 50,
|
|
586
586
|
y: (Math.random() - 0.5) * 50,
|
|
587
587
|
z: (Math.random() - 0.5) * 50
|
|
588
|
-
},
|
|
588
|
+
}, i = {
|
|
589
589
|
...e,
|
|
590
590
|
position: t,
|
|
591
591
|
velocity: { x: 0, y: 0, z: 0 },
|
|
592
592
|
mass: 1
|
|
593
|
-
},
|
|
593
|
+
}, o = this.nodeFactory.createNode(
|
|
594
594
|
{ ...e, position: t },
|
|
595
595
|
s
|
|
596
596
|
);
|
|
597
|
-
return this.sceneManager.add(
|
|
597
|
+
return this.sceneManager.add(o.group), this.nodes.set(e.id, i), this.nodeObjects.set(e.id, o), !0;
|
|
598
598
|
}
|
|
599
599
|
/**
|
|
600
600
|
* Removes a node from the graph
|
|
@@ -608,17 +608,17 @@ class ft {
|
|
|
608
608
|
* Updates a node's properties
|
|
609
609
|
*/
|
|
610
610
|
updateNode(e, s) {
|
|
611
|
-
const t = this.nodes.get(e),
|
|
612
|
-
return !t || !
|
|
613
|
-
|
|
611
|
+
const t = this.nodes.get(e), i = this.nodeObjects.get(e);
|
|
612
|
+
return !t || !i ? (console.warn(`[ForceGraph3D] Node "${e}" not found`), !1) : (s.label !== void 0 && (t.label = s.label, this.nodeFactory.updateNodeLabel(i, s.label)), s.color !== void 0 && (t.color = s.color, this.nodeFactory.updateNodeColor(i, s.color)), Object.keys(s).forEach((o) => {
|
|
613
|
+
o !== "id" && o !== "label" && o !== "color" && o !== "position" && (t[o] = s[o]);
|
|
614
614
|
}), !0);
|
|
615
615
|
}
|
|
616
616
|
/**
|
|
617
617
|
* Updates a node's position (called by physics engine)
|
|
618
618
|
*/
|
|
619
619
|
updateNodePosition(e, s) {
|
|
620
|
-
const t = this.nodes.get(e),
|
|
621
|
-
t &&
|
|
620
|
+
const t = this.nodes.get(e), i = this.nodeObjects.get(e);
|
|
621
|
+
t && i && (t.position = s, i.group.position.set(s.x, s.y, s.z));
|
|
622
622
|
}
|
|
623
623
|
/**
|
|
624
624
|
* Updates a node's LOD level
|
|
@@ -716,14 +716,14 @@ class mt {
|
|
|
716
716
|
const s = D(e.source, e.target);
|
|
717
717
|
if (this.edgeKeySet.has(s))
|
|
718
718
|
return console.warn(`[ForceGraph3D] Edge "${e.source}" -> "${e.target}" already exists`), !1;
|
|
719
|
-
const t = this.nodeManager.getNode(e.source),
|
|
719
|
+
const t = this.nodeManager.getNode(e.source), i = this.nodeManager.getNode(e.target), o = this.edgeFactory.createEdge(
|
|
720
720
|
e,
|
|
721
721
|
t,
|
|
722
|
-
|
|
722
|
+
i,
|
|
723
723
|
t.position,
|
|
724
|
-
|
|
724
|
+
i.position
|
|
725
725
|
);
|
|
726
|
-
return this.sceneManager.add(
|
|
726
|
+
return this.sceneManager.add(o.line), this.edges.push(e), this.edgeObjects.push(o), this.edgeKeySet.add(s), !0;
|
|
727
727
|
}
|
|
728
728
|
/**
|
|
729
729
|
* Removes an edge from the graph
|
|
@@ -733,13 +733,13 @@ class mt {
|
|
|
733
733
|
const t = D(e, s);
|
|
734
734
|
if (!this.edgeKeySet.has(t))
|
|
735
735
|
return !1;
|
|
736
|
-
const
|
|
736
|
+
const i = this.edges.findIndex(
|
|
737
737
|
(a) => D(a.source, a.target) === t
|
|
738
738
|
);
|
|
739
|
-
if (
|
|
739
|
+
if (i === -1)
|
|
740
740
|
return !1;
|
|
741
|
-
const
|
|
742
|
-
return this.sceneManager.remove(
|
|
741
|
+
const o = this.edgeObjects[i];
|
|
742
|
+
return this.sceneManager.remove(o.line), this.edgeFactory.disposeEdge(o), this.edges.splice(i, 1), this.edgeObjects.splice(i, 1), this.edgeKeySet.delete(t), this.highlightedEdgeKey === t && (this.highlightedEdgeKey = null), !0;
|
|
743
743
|
}
|
|
744
744
|
/**
|
|
745
745
|
* Highlights an edge
|
|
@@ -747,10 +747,10 @@ class mt {
|
|
|
747
747
|
highlightEdge(e, s) {
|
|
748
748
|
const t = D(e, s);
|
|
749
749
|
this.highlightedEdgeKey && this.highlightedEdgeKey !== t && this.unhighlightCurrentEdge();
|
|
750
|
-
const
|
|
751
|
-
(
|
|
750
|
+
const i = this.edges.findIndex(
|
|
751
|
+
(o) => D(o.source, o.target) === t
|
|
752
752
|
);
|
|
753
|
-
|
|
753
|
+
i !== -1 && (this.edgeFactory.highlightEdge(this.edgeObjects[i]), this.highlightedEdgeKey = t);
|
|
754
754
|
}
|
|
755
755
|
/**
|
|
756
756
|
* Unhighlights the currently highlighted edge
|
|
@@ -793,11 +793,11 @@ class mt {
|
|
|
793
793
|
*/
|
|
794
794
|
updateEdgePositions() {
|
|
795
795
|
this.edgeObjects.forEach((e, s) => {
|
|
796
|
-
const t = this.edges[s],
|
|
797
|
-
|
|
796
|
+
const t = this.edges[s], i = this.nodeManager.getNode(t.source), o = this.nodeManager.getNode(t.target);
|
|
797
|
+
i && o && this.edgeFactory.updateEdgePositions(
|
|
798
798
|
e,
|
|
799
|
-
|
|
800
|
-
|
|
799
|
+
i.position,
|
|
800
|
+
o.position
|
|
801
801
|
);
|
|
802
802
|
});
|
|
803
803
|
}
|
|
@@ -865,13 +865,13 @@ class Le {
|
|
|
865
865
|
calculateRepulsionBruteForce() {
|
|
866
866
|
const e = Array.from(this.nodes.values()), s = e.length;
|
|
867
867
|
for (let t = 0; t < s; t++) {
|
|
868
|
-
const
|
|
869
|
-
for (let
|
|
870
|
-
const a = e[
|
|
871
|
-
let
|
|
872
|
-
|
|
873
|
-
const
|
|
874
|
-
|
|
868
|
+
const i = e[t];
|
|
869
|
+
for (let o = t + 1; o < s; o++) {
|
|
870
|
+
const a = e[o], r = a.position.x - i.position.x, c = a.position.y - i.position.y, d = a.position.z - i.position.z;
|
|
871
|
+
let p = r * r + c * c + d * d;
|
|
872
|
+
p < 0.01 && (p = 0.01);
|
|
873
|
+
const x = Math.sqrt(p), f = this.repulsionStrength * this.alpha / p, u = r / x * f, y = c / x * f, b = d / x * f;
|
|
874
|
+
i.velocity.x -= u / i.mass, i.velocity.y -= y / i.mass, i.velocity.z -= b / i.mass, a.velocity.x += u / a.mass, a.velocity.y += y / a.mass, a.velocity.z += b / a.mass;
|
|
875
875
|
}
|
|
876
876
|
}
|
|
877
877
|
}
|
|
@@ -892,10 +892,10 @@ class Le {
|
|
|
892
892
|
return;
|
|
893
893
|
}
|
|
894
894
|
if (s.mass === 0) return;
|
|
895
|
-
const t = s.centerOfMass.x - e.position.x,
|
|
895
|
+
const t = s.centerOfMass.x - e.position.x, i = s.centerOfMass.y - e.position.y, o = s.centerOfMass.z - e.position.z, a = Math.sqrt(t * t + i * i + o * o);
|
|
896
896
|
if (s.size / a < this.barnesHutTheta) {
|
|
897
897
|
const r = Math.max(a * a, 0.01), c = this.repulsionStrength * this.alpha * s.mass / r;
|
|
898
|
-
e.velocity.x -= t / a * c / e.mass, e.velocity.y -=
|
|
898
|
+
e.velocity.x -= t / a * c / e.mass, e.velocity.y -= i / a * c / e.mass, e.velocity.z -= o / a * c / e.mass;
|
|
899
899
|
} else
|
|
900
900
|
for (const r of s.children)
|
|
901
901
|
r && this.calculateForceFromOctree(e, r);
|
|
@@ -904,11 +904,11 @@ class Le {
|
|
|
904
904
|
* Apply repulsion between two nodes
|
|
905
905
|
*/
|
|
906
906
|
applyRepulsionBetween(e, s) {
|
|
907
|
-
const t = s.position.x - e.position.x,
|
|
908
|
-
let a = t * t +
|
|
907
|
+
const t = s.position.x - e.position.x, i = s.position.y - e.position.y, o = s.position.z - e.position.z;
|
|
908
|
+
let a = t * t + i * i + o * o;
|
|
909
909
|
a < 0.01 && (a = 0.01);
|
|
910
910
|
const r = Math.sqrt(a), c = this.repulsionStrength * this.alpha / a;
|
|
911
|
-
e.velocity.x -= t / r * c / e.mass, e.velocity.y -=
|
|
911
|
+
e.velocity.x -= t / r * c / e.mass, e.velocity.y -= i / r * c / e.mass, e.velocity.z -= o / r * c / e.mass;
|
|
912
912
|
}
|
|
913
913
|
/**
|
|
914
914
|
* Calculate attraction forces along edges
|
|
@@ -917,10 +917,10 @@ class Le {
|
|
|
917
917
|
for (const e of this.edges) {
|
|
918
918
|
const s = this.nodes.get(e.source), t = this.nodes.get(e.target);
|
|
919
919
|
if (!s || !t) continue;
|
|
920
|
-
const
|
|
920
|
+
const i = t.position.x - s.position.x, o = t.position.y - s.position.y, a = t.position.z - s.position.z, r = Math.sqrt(i * i + o * o + a * a);
|
|
921
921
|
if (r < 0.01) continue;
|
|
922
|
-
const d = (r - 15) * this.attractionStrength * this.alpha,
|
|
923
|
-
s.velocity.x +=
|
|
922
|
+
const d = (r - 15) * this.attractionStrength * this.alpha, p = i / r * d, x = o / r * d, f = a / r * d;
|
|
923
|
+
s.velocity.x += p / s.mass, s.velocity.y += x / s.mass, s.velocity.z += f / s.mass, t.velocity.x -= p / t.mass, t.velocity.y -= x / t.mass, t.velocity.z -= f / t.mass;
|
|
924
924
|
}
|
|
925
925
|
}
|
|
926
926
|
/**
|
|
@@ -968,13 +968,13 @@ class yt {
|
|
|
968
968
|
max: { x: 100, y: 100, z: 100 }
|
|
969
969
|
};
|
|
970
970
|
const s = { x: 1 / 0, y: 1 / 0, z: 1 / 0 }, t = { x: -1 / 0, y: -1 / 0, z: -1 / 0 };
|
|
971
|
-
for (const
|
|
972
|
-
s.x = Math.min(s.x,
|
|
973
|
-
const
|
|
974
|
-
return s.x -=
|
|
971
|
+
for (const o of e)
|
|
972
|
+
s.x = Math.min(s.x, o.position.x), s.y = Math.min(s.y, o.position.y), s.z = Math.min(s.z, o.position.z), t.x = Math.max(t.x, o.position.x), t.y = Math.max(t.y, o.position.y), t.z = Math.max(t.z, o.position.z);
|
|
973
|
+
const i = 10;
|
|
974
|
+
return s.x -= i, s.y -= i, s.z -= i, t.x += i, t.y += i, t.z += i, { min: s, max: t };
|
|
975
975
|
}
|
|
976
976
|
buildTree(e, s, t = 0) {
|
|
977
|
-
const
|
|
977
|
+
const i = Math.max(
|
|
978
978
|
s.max.x - s.min.x,
|
|
979
979
|
s.max.y - s.min.y,
|
|
980
980
|
s.max.z - s.min.z
|
|
@@ -982,7 +982,7 @@ class yt {
|
|
|
982
982
|
if (e.length === 0)
|
|
983
983
|
return {
|
|
984
984
|
bounds: s,
|
|
985
|
-
size:
|
|
985
|
+
size: i,
|
|
986
986
|
centerOfMass: { x: 0, y: 0, z: 0 },
|
|
987
987
|
mass: 0,
|
|
988
988
|
isLeaf: !0,
|
|
@@ -990,56 +990,56 @@ class yt {
|
|
|
990
990
|
children: []
|
|
991
991
|
};
|
|
992
992
|
if (e.length === 1 || t > 20) {
|
|
993
|
-
let
|
|
994
|
-
const
|
|
995
|
-
for (const
|
|
996
|
-
|
|
997
|
-
return
|
|
993
|
+
let u = 0;
|
|
994
|
+
const y = { x: 0, y: 0, z: 0 };
|
|
995
|
+
for (const b of e)
|
|
996
|
+
u += b.mass, y.x += b.position.x * b.mass, y.y += b.position.y * b.mass, y.z += b.position.z * b.mass;
|
|
997
|
+
return u > 0 && (y.x /= u, y.y /= u, y.z /= u), {
|
|
998
998
|
bounds: s,
|
|
999
|
-
size:
|
|
1000
|
-
centerOfMass:
|
|
1001
|
-
mass:
|
|
999
|
+
size: i,
|
|
1000
|
+
centerOfMass: y,
|
|
1001
|
+
mass: u,
|
|
1002
1002
|
isLeaf: !0,
|
|
1003
1003
|
node: e[0],
|
|
1004
1004
|
children: []
|
|
1005
1005
|
};
|
|
1006
1006
|
}
|
|
1007
|
-
const
|
|
1008
|
-
for (const
|
|
1009
|
-
const
|
|
1010
|
-
c[
|
|
1007
|
+
const o = (s.min.x + s.max.x) / 2, a = (s.min.y + s.max.y) / 2, r = (s.min.z + s.max.z) / 2, c = [[], [], [], [], [], [], [], []];
|
|
1008
|
+
for (const u of e) {
|
|
1009
|
+
const y = (u.position.x >= o ? 1 : 0) + (u.position.y >= a ? 2 : 0) + (u.position.z >= r ? 4 : 0);
|
|
1010
|
+
c[y].push(u);
|
|
1011
1011
|
}
|
|
1012
1012
|
const d = [
|
|
1013
|
-
{ min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x:
|
|
1014
|
-
{ min: { x:
|
|
1015
|
-
{ min: { x: s.min.x, y: a, z: s.min.z }, max: { x:
|
|
1016
|
-
{ min: { x:
|
|
1017
|
-
{ min: { x: s.min.x, y: s.min.y, z: r }, max: { x:
|
|
1018
|
-
{ min: { x:
|
|
1019
|
-
{ min: { x: s.min.x, y: a, z: r }, max: { x:
|
|
1020
|
-
{ min: { x:
|
|
1021
|
-
],
|
|
1022
|
-
let
|
|
1023
|
-
const
|
|
1024
|
-
for (let
|
|
1025
|
-
if (c[
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1013
|
+
{ min: { x: s.min.x, y: s.min.y, z: s.min.z }, max: { x: o, y: a, z: r } },
|
|
1014
|
+
{ min: { x: o, y: s.min.y, z: s.min.z }, max: { x: s.max.x, y: a, z: r } },
|
|
1015
|
+
{ min: { x: s.min.x, y: a, z: s.min.z }, max: { x: o, y: s.max.y, z: r } },
|
|
1016
|
+
{ min: { x: o, y: a, z: s.min.z }, max: { x: s.max.x, y: s.max.y, z: r } },
|
|
1017
|
+
{ min: { x: s.min.x, y: s.min.y, z: r }, max: { x: o, y: a, z: s.max.z } },
|
|
1018
|
+
{ min: { x: o, y: s.min.y, z: r }, max: { x: s.max.x, y: a, z: s.max.z } },
|
|
1019
|
+
{ min: { x: s.min.x, y: a, z: r }, max: { x: o, y: s.max.y, z: s.max.z } },
|
|
1020
|
+
{ min: { x: o, y: a, z: r }, max: { x: s.max.x, y: s.max.y, z: s.max.z } }
|
|
1021
|
+
], p = [];
|
|
1022
|
+
let x = 0;
|
|
1023
|
+
const f = { x: 0, y: 0, z: 0 };
|
|
1024
|
+
for (let u = 0; u < 8; u++)
|
|
1025
|
+
if (c[u].length > 0) {
|
|
1026
|
+
const y = this.buildTree(c[u], d[u], t + 1);
|
|
1027
|
+
p.push(y), x += y.mass, f.x += y.centerOfMass.x * y.mass, f.y += y.centerOfMass.y * y.mass, f.z += y.centerOfMass.z * y.mass;
|
|
1028
1028
|
} else
|
|
1029
|
-
|
|
1030
|
-
return
|
|
1029
|
+
p.push(null);
|
|
1030
|
+
return x > 0 && (f.x /= x, f.y /= x, f.z /= x), {
|
|
1031
1031
|
bounds: s,
|
|
1032
|
-
size:
|
|
1033
|
-
centerOfMass:
|
|
1034
|
-
mass:
|
|
1032
|
+
size: i,
|
|
1033
|
+
centerOfMass: f,
|
|
1034
|
+
mass: x,
|
|
1035
1035
|
isLeaf: !1,
|
|
1036
1036
|
node: null,
|
|
1037
|
-
children:
|
|
1037
|
+
children: p
|
|
1038
1038
|
};
|
|
1039
1039
|
}
|
|
1040
1040
|
}
|
|
1041
1041
|
class xt {
|
|
1042
|
-
constructor(e, s, t,
|
|
1042
|
+
constructor(e, s, t, i = 60) {
|
|
1043
1043
|
l(this, "sceneManager");
|
|
1044
1044
|
l(this, "animationId", null);
|
|
1045
1045
|
l(this, "isRunning", !1);
|
|
@@ -1064,7 +1064,7 @@ class xt {
|
|
|
1064
1064
|
const t = e - this.fpsStartTime;
|
|
1065
1065
|
t >= 1e3 && (this.currentFPS = this.frameCount / (t / 1e3), this.frameCount = 0, this.fpsStartTime = e), this.onSimulate(), this.onRender(), this.sceneManager.render();
|
|
1066
1066
|
});
|
|
1067
|
-
this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 /
|
|
1067
|
+
this.sceneManager = e, this.onSimulate = s, this.onRender = t, this.frameInterval = 1e3 / i;
|
|
1068
1068
|
}
|
|
1069
1069
|
/**
|
|
1070
1070
|
* Starts the animation loop
|
|
@@ -1141,10 +1141,10 @@ class bt {
|
|
|
1141
1141
|
{ colors: ["#2d1a1a", "#1a0a0a", "#0f0505"] }
|
|
1142
1142
|
// -z
|
|
1143
1143
|
];
|
|
1144
|
-
for (const
|
|
1145
|
-
const
|
|
1146
|
-
|
|
1147
|
-
const a =
|
|
1144
|
+
for (const i of t) {
|
|
1145
|
+
const o = document.createElement("canvas");
|
|
1146
|
+
o.width = 256, o.height = 256;
|
|
1147
|
+
const a = o.getContext("2d"), r = a.createRadialGradient(
|
|
1148
1148
|
256 / 2,
|
|
1149
1149
|
256 / 2,
|
|
1150
1150
|
0,
|
|
@@ -1152,17 +1152,17 @@ class bt {
|
|
|
1152
1152
|
256 / 2,
|
|
1153
1153
|
256 * 0.8
|
|
1154
1154
|
);
|
|
1155
|
-
r.addColorStop(0,
|
|
1155
|
+
r.addColorStop(0, i.colors[0]), r.addColorStop(0.5, i.colors[1]), r.addColorStop(1, i.colors[2]), a.fillStyle = r, a.fillRect(0, 0, 256, 256);
|
|
1156
1156
|
const c = a.getImageData(0, 0, 256, 256);
|
|
1157
1157
|
for (let d = 0; d < c.data.length; d += 4) {
|
|
1158
|
-
const
|
|
1159
|
-
c.data[d] = Math.min(255, Math.max(0, c.data[d] +
|
|
1158
|
+
const p = (Math.random() - 0.5) * 5;
|
|
1159
|
+
c.data[d] = Math.min(255, Math.max(0, c.data[d] + p)), c.data[d + 1] = Math.min(255, Math.max(0, c.data[d + 1] + p)), c.data[d + 2] = Math.min(255, Math.max(0, c.data[d + 2] + p));
|
|
1160
1160
|
}
|
|
1161
|
-
a.putImageData(c, 0, 0), s.push(
|
|
1161
|
+
a.putImageData(c, 0, 0), s.push(o);
|
|
1162
1162
|
}
|
|
1163
|
-
this.envMap = new m.CubeTexture(s.map((
|
|
1164
|
-
const
|
|
1165
|
-
return
|
|
1163
|
+
this.envMap = new m.CubeTexture(s.map((i) => {
|
|
1164
|
+
const o = new Image();
|
|
1165
|
+
return o.src = i.toDataURL(), o;
|
|
1166
1166
|
})), this.envMap.needsUpdate = !0;
|
|
1167
1167
|
}
|
|
1168
1168
|
/**
|
|
@@ -1179,9 +1179,9 @@ class bt {
|
|
|
1179
1179
|
const t = "glass-single";
|
|
1180
1180
|
if (this.materialCache.has(t))
|
|
1181
1181
|
return this.materialCache.get(t).clone();
|
|
1182
|
-
const
|
|
1182
|
+
const i = new m.Color(16750950), o = new m.ShaderMaterial({
|
|
1183
1183
|
uniforms: {
|
|
1184
|
-
uColor: { value:
|
|
1184
|
+
uColor: { value: i },
|
|
1185
1185
|
uEnvMap: { value: this.envMap },
|
|
1186
1186
|
uGlowColor: { value: new m.Color(16777215) },
|
|
1187
1187
|
uGlowIntensity: { value: 0.8 },
|
|
@@ -1253,7 +1253,7 @@ class bt {
|
|
|
1253
1253
|
depthWrite: !0,
|
|
1254
1254
|
blending: m.NormalBlending
|
|
1255
1255
|
});
|
|
1256
|
-
return this.materialCache.set(t,
|
|
1256
|
+
return this.materialCache.set(t, o), o.clone();
|
|
1257
1257
|
}
|
|
1258
1258
|
/**
|
|
1259
1259
|
* Creates material for edges (light color for dark background)
|
|
@@ -1282,10 +1282,10 @@ class bt {
|
|
|
1282
1282
|
* Creates a sprite material for labels (light text for dark background)
|
|
1283
1283
|
*/
|
|
1284
1284
|
createLabelMaterial(e, s = 24) {
|
|
1285
|
-
const t = document.createElement("canvas"),
|
|
1286
|
-
|
|
1287
|
-
const a =
|
|
1288
|
-
t.width = Math.max(128, a + 24), t.height = s + 20,
|
|
1285
|
+
const t = document.createElement("canvas"), i = t.getContext("2d");
|
|
1286
|
+
i.font = `600 ${s}px Inter, -apple-system, sans-serif`;
|
|
1287
|
+
const a = i.measureText(e).width;
|
|
1288
|
+
t.width = Math.max(128, a + 24), t.height = s + 20, i.clearRect(0, 0, t.width, t.height), i.font = `600 ${s}px Inter, -apple-system, sans-serif`, i.textAlign = "center", i.textBaseline = "middle", i.shadowColor = "rgba(0, 0, 0, 0.8)", i.shadowBlur = 4, i.shadowOffsetX = 1, i.shadowOffsetY = 1, i.fillStyle = "rgba(255, 255, 255, 0.95)", i.fillText(e, t.width / 2, t.height / 2);
|
|
1289
1289
|
const r = new m.CanvasTexture(t);
|
|
1290
1290
|
return r.needsUpdate = !0, new m.SpriteMaterial({
|
|
1291
1291
|
map: r,
|
|
@@ -1308,13 +1308,13 @@ class bt {
|
|
|
1308
1308
|
}
|
|
1309
1309
|
}
|
|
1310
1310
|
class vt {
|
|
1311
|
-
constructor(e, s = 2, t = [32, 16, 8],
|
|
1311
|
+
constructor(e, s = 2, t = [32, 16, 8], i = 16750950) {
|
|
1312
1312
|
l(this, "materialFactory");
|
|
1313
1313
|
l(this, "geometryCache", /* @__PURE__ */ new Map());
|
|
1314
1314
|
l(this, "nodeRadius");
|
|
1315
1315
|
l(this, "lodSegments");
|
|
1316
1316
|
l(this, "defaultNodeColor");
|
|
1317
|
-
this.materialFactory = e, this.nodeRadius = s, this.lodSegments = t, this.defaultNodeColor =
|
|
1317
|
+
this.materialFactory = e, this.nodeRadius = s, this.lodSegments = t, this.defaultNodeColor = i, this.initGeometryCache();
|
|
1318
1318
|
}
|
|
1319
1319
|
/**
|
|
1320
1320
|
* Pre-create geometries for each LOD level
|
|
@@ -1341,9 +1341,9 @@ class vt {
|
|
|
1341
1341
|
createNode(e, s = 0) {
|
|
1342
1342
|
const t = new m.Group();
|
|
1343
1343
|
t.name = `node-${e.id}`, t.userData = { nodeId: e.id, nodeData: e };
|
|
1344
|
-
const
|
|
1344
|
+
const i = this.getGeometry(s), o = this.materialFactory.createGlassMaterial(
|
|
1345
1345
|
e.color ?? this.defaultNodeColor
|
|
1346
|
-
), a = new m.Mesh(
|
|
1346
|
+
), a = new m.Mesh(i, o);
|
|
1347
1347
|
a.castShadow = !0, a.receiveShadow = !0, t.add(a);
|
|
1348
1348
|
const r = this.materialFactory.createLabelMaterial(e.label), c = new m.Sprite(r);
|
|
1349
1349
|
return c.position.y = this.nodeRadius + 1.5, c.scale.set(4, 1, 1), t.add(c), e.position && t.position.set(
|
|
@@ -1417,14 +1417,14 @@ class Mt {
|
|
|
1417
1417
|
/**
|
|
1418
1418
|
* Creates an edge line between two positions
|
|
1419
1419
|
*/
|
|
1420
|
-
createEdge(e, s, t,
|
|
1420
|
+
createEdge(e, s, t, i, o) {
|
|
1421
1421
|
const a = new m.BufferGeometry(), r = new Float32Array([
|
|
1422
|
-
o.x,
|
|
1423
|
-
o.y,
|
|
1424
|
-
o.z,
|
|
1425
1422
|
i.x,
|
|
1426
1423
|
i.y,
|
|
1427
|
-
i.z
|
|
1424
|
+
i.z,
|
|
1425
|
+
o.x,
|
|
1426
|
+
o.y,
|
|
1427
|
+
o.z
|
|
1428
1428
|
]);
|
|
1429
1429
|
a.setAttribute("position", new m.BufferAttribute(r, 3));
|
|
1430
1430
|
const c = this.getDefaultMaterial().clone(), d = new m.Line(a, c);
|
|
@@ -1456,8 +1456,8 @@ class Mt {
|
|
|
1456
1456
|
* Updates an edge's positions
|
|
1457
1457
|
*/
|
|
1458
1458
|
updateEdgePositions(e, s, t) {
|
|
1459
|
-
const
|
|
1460
|
-
|
|
1459
|
+
const i = e.line.geometry.attributes.position, o = i.array;
|
|
1460
|
+
o[0] = s.x, o[1] = s.y, o[2] = s.z, o[3] = t.x, o[4] = t.y, o[5] = t.z, i.needsUpdate = !0, e.line.geometry.computeBoundingSphere();
|
|
1461
1461
|
}
|
|
1462
1462
|
/**
|
|
1463
1463
|
* Disposes an edge's resources
|
|
@@ -1485,15 +1485,15 @@ class wt {
|
|
|
1485
1485
|
getLODLevel(e) {
|
|
1486
1486
|
if (!this.enabled)
|
|
1487
1487
|
return U.HIGH;
|
|
1488
|
-
const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y,
|
|
1489
|
-
return
|
|
1488
|
+
const s = e.x - this.camera.position.x, t = e.y - this.camera.position.y, i = e.z - this.camera.position.z, o = Math.sqrt(s * s + t * t + i * i);
|
|
1489
|
+
return o < this.lodDistances[0] ? U.HIGH : o < this.lodDistances[1] ? U.MEDIUM : U.LOW;
|
|
1490
1490
|
}
|
|
1491
1491
|
/**
|
|
1492
1492
|
* Checks if a node should be visible based on distance
|
|
1493
1493
|
*/
|
|
1494
1494
|
shouldRenderNode(e, s = 500) {
|
|
1495
|
-
const t = e.x - this.camera.position.x,
|
|
1496
|
-
return Math.sqrt(t * t +
|
|
1495
|
+
const t = e.x - this.camera.position.x, i = e.y - this.camera.position.y, o = e.z - this.camera.position.z;
|
|
1496
|
+
return Math.sqrt(t * t + i * i + o * o) < s;
|
|
1497
1497
|
}
|
|
1498
1498
|
/**
|
|
1499
1499
|
* Sets the LOD distances
|
|
@@ -1549,14 +1549,14 @@ class Et {
|
|
|
1549
1549
|
*/
|
|
1550
1550
|
isLineVisible(e, s) {
|
|
1551
1551
|
if (!this.enabled) return !0;
|
|
1552
|
-
const t = new m.Vector3(e.x, e.y, e.z),
|
|
1553
|
-
if (this.frustum.containsPoint(t) || this.frustum.containsPoint(
|
|
1552
|
+
const t = new m.Vector3(e.x, e.y, e.z), i = new m.Vector3(s.x, s.y, s.z);
|
|
1553
|
+
if (this.frustum.containsPoint(t) || this.frustum.containsPoint(i))
|
|
1554
1554
|
return !0;
|
|
1555
|
-
const
|
|
1555
|
+
const o = new m.Vector3(
|
|
1556
1556
|
(e.x + s.x) / 2,
|
|
1557
1557
|
(e.y + s.y) / 2,
|
|
1558
1558
|
(e.z + s.z) / 2
|
|
1559
|
-
), a =
|
|
1559
|
+
), a = o.distanceTo(t), r = new m.Sphere(o, a);
|
|
1560
1560
|
return this.frustum.intersectsSphere(r);
|
|
1561
1561
|
}
|
|
1562
1562
|
/**
|
|
@@ -1580,7 +1580,7 @@ class Ct {
|
|
|
1580
1580
|
l(this, "hoveredEdgeKey", null);
|
|
1581
1581
|
l(this, "nodeObjects", []);
|
|
1582
1582
|
l(this, "edgeObjects", []);
|
|
1583
|
-
this.sceneManager = e, this.container = s, this.raycaster = new m.Raycaster(), this.raycaster.params.Line = { threshold:
|
|
1583
|
+
this.sceneManager = e, this.container = s, this.raycaster = new m.Raycaster(), this.raycaster.params.Line = { threshold: 1.5 }, this.mouse = new m.Vector2(), this.handleClick = this.handleClick.bind(this), this.handleMouseMove = this.handleMouseMove.bind(this), s.addEventListener("click", this.handleClick), s.addEventListener("mousemove", this.handleMouseMove);
|
|
1584
1584
|
}
|
|
1585
1585
|
/**
|
|
1586
1586
|
* Updates the list of node objects to raycast against
|
|
@@ -1639,23 +1639,23 @@ class Ct {
|
|
|
1639
1639
|
this.hoveredEdgeKey !== null && this.onEdgeHover && (this.hoveredEdgeKey = null, this.onEdgeHover(null)), this.container.style.cursor = "pointer";
|
|
1640
1640
|
return;
|
|
1641
1641
|
}
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1642
|
+
const i = this.getIntersectedEdge(e), o = i ? `${i.edge.source}-${i.edge.target}` : null;
|
|
1643
|
+
o !== this.hoveredEdgeKey && (this.hoveredEdgeKey = o, this.onEdgeHover && this.onEdgeHover(i)), this.container.style.cursor = i ? "pointer" : "default";
|
|
1644
1644
|
}
|
|
1645
1645
|
/**
|
|
1646
1646
|
* Gets the intersected node from a mouse event
|
|
1647
1647
|
*/
|
|
1648
1648
|
getIntersectedNode(e) {
|
|
1649
|
-
var
|
|
1649
|
+
var i;
|
|
1650
1650
|
const s = this.container.getBoundingClientRect();
|
|
1651
1651
|
this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
|
|
1652
1652
|
const t = this.raycaster.intersectObjects(this.nodeObjects, !0);
|
|
1653
1653
|
if (t.length > 0) {
|
|
1654
|
-
let
|
|
1655
|
-
for (;
|
|
1656
|
-
if ((
|
|
1657
|
-
return
|
|
1658
|
-
|
|
1654
|
+
let o = t[0].object;
|
|
1655
|
+
for (; o; ) {
|
|
1656
|
+
if ((i = o.userData) != null && i.nodeData)
|
|
1657
|
+
return o.userData.nodeData;
|
|
1658
|
+
o = o.parent;
|
|
1659
1659
|
}
|
|
1660
1660
|
}
|
|
1661
1661
|
return null;
|
|
@@ -1668,13 +1668,13 @@ class Ct {
|
|
|
1668
1668
|
this.mouse.x = (e.clientX - s.left) / s.width * 2 - 1, this.mouse.y = -((e.clientY - s.top) / s.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
|
|
1669
1669
|
const t = this.raycaster.intersectObjects(this.edgeObjects, !1);
|
|
1670
1670
|
if (t.length > 0) {
|
|
1671
|
-
const
|
|
1672
|
-
if (
|
|
1671
|
+
const i = t[0].object, o = i.userData;
|
|
1672
|
+
if (o != null && o.edge && (o != null && o.sourceNode) && (o != null && o.targetNode))
|
|
1673
1673
|
return {
|
|
1674
|
-
edge:
|
|
1675
|
-
sourceNode:
|
|
1676
|
-
targetNode:
|
|
1677
|
-
edgeLine:
|
|
1674
|
+
edge: o.edge,
|
|
1675
|
+
sourceNode: o.sourceNode,
|
|
1676
|
+
targetNode: o.targetNode,
|
|
1677
|
+
edgeLine: i
|
|
1678
1678
|
};
|
|
1679
1679
|
}
|
|
1680
1680
|
return null;
|
|
@@ -1683,14 +1683,14 @@ class Ct {
|
|
|
1683
1683
|
* Performs a raycast and returns the intersected node ID
|
|
1684
1684
|
*/
|
|
1685
1685
|
getIntersectedNodeId(e, s) {
|
|
1686
|
-
var
|
|
1686
|
+
var o;
|
|
1687
1687
|
const t = this.container.getBoundingClientRect();
|
|
1688
1688
|
this.mouse.x = (e - t.left) / t.width * 2 - 1, this.mouse.y = -((s - t.top) / t.height) * 2 + 1, this.raycaster.setFromCamera(this.mouse, this.sceneManager.camera);
|
|
1689
|
-
const
|
|
1690
|
-
if (
|
|
1691
|
-
let a =
|
|
1689
|
+
const i = this.raycaster.intersectObjects(this.nodeObjects, !0);
|
|
1690
|
+
if (i.length > 0) {
|
|
1691
|
+
let a = i[0].object;
|
|
1692
1692
|
for (; a; ) {
|
|
1693
|
-
if ((
|
|
1693
|
+
if ((o = a.userData) != null && o.nodeId)
|
|
1694
1694
|
return a.userData.nodeId;
|
|
1695
1695
|
a = a.parent;
|
|
1696
1696
|
}
|
|
@@ -1774,10 +1774,10 @@ class Nt {
|
|
|
1774
1774
|
this.currentNodeId = e.id;
|
|
1775
1775
|
let t;
|
|
1776
1776
|
this.panelTemplate ? t = this.panelTemplate(e, s) : t = this.generateDefaultContent(e, s), this.panel.innerHTML = t;
|
|
1777
|
-
const
|
|
1778
|
-
|
|
1777
|
+
const i = this.panel.querySelector('[data-action="expand"]'), o = this.panel.querySelector("[data-depth-select]");
|
|
1778
|
+
i && this.onExpand && i.addEventListener("click", () => {
|
|
1779
1779
|
if (this.currentNodeId) {
|
|
1780
|
-
const r =
|
|
1780
|
+
const r = o ? parseInt(o.value, 10) : 1;
|
|
1781
1781
|
this.onExpand(this.currentNodeId, r);
|
|
1782
1782
|
}
|
|
1783
1783
|
});
|
|
@@ -1936,7 +1936,7 @@ class Nt {
|
|
|
1936
1936
|
<div class="neighbors-section">
|
|
1937
1937
|
<div class="neighbors-title">Connected To</div>
|
|
1938
1938
|
${s.slice(0, 5).map(
|
|
1939
|
-
(
|
|
1939
|
+
(i) => `<span class="neighbor-chip">${this.escapeHtml(i.label)}</span>`
|
|
1940
1940
|
).join("")}
|
|
1941
1941
|
${s.length > 5 ? `<span class="neighbor-chip">+${s.length - 5} more</span>` : ""}
|
|
1942
1942
|
</div>
|
|
@@ -2054,10 +2054,10 @@ class St {
|
|
|
2054
2054
|
show(e, s, t) {
|
|
2055
2055
|
if (!this.panel) return;
|
|
2056
2056
|
this.currentEdgeKey = `${e.source}-${e.target}`;
|
|
2057
|
-
let
|
|
2058
|
-
this.panelTemplate ?
|
|
2059
|
-
const
|
|
2060
|
-
|
|
2057
|
+
let i;
|
|
2058
|
+
this.panelTemplate ? i = this.panelTemplate(e, s, t) : i = this.generateDefaultContent(e, s, t), this.panel.innerHTML = i;
|
|
2059
|
+
const o = this.panel.querySelector('[data-action="close"]');
|
|
2060
|
+
o && o.addEventListener("click", () => {
|
|
2061
2061
|
this.hide(), this.onClose && this.onClose();
|
|
2062
2062
|
});
|
|
2063
2063
|
const a = this.panel.querySelector('[data-action="goto-source"]');
|
|
@@ -2073,7 +2073,7 @@ class St {
|
|
|
2073
2073
|
* Generates default panel content
|
|
2074
2074
|
*/
|
|
2075
2075
|
generateDefaultContent(e, s, t) {
|
|
2076
|
-
const
|
|
2076
|
+
const i = s.color ? `#${s.color.toString(16).padStart(6, "0")}` : "#ff9966", o = t.color ? `#${t.color.toString(16).padStart(6, "0")}` : "#ff9966", a = e.relationship || "connected to";
|
|
2077
2077
|
return `
|
|
2078
2078
|
<style>
|
|
2079
2079
|
.force-graph-edge-panel .panel-header {
|
|
@@ -2183,7 +2183,7 @@ class St {
|
|
|
2183
2183
|
<div class="node-card" data-action="goto-source" title="Click to focus on ${this.escapeHtml(s.label)}">
|
|
2184
2184
|
<div class="node-type">Source</div>
|
|
2185
2185
|
<div class="node-card-header">
|
|
2186
|
-
<span class="color-dot" style="background: ${
|
|
2186
|
+
<span class="color-dot" style="background: ${i}; box-shadow: 0 0 8px ${i}80;"></span>
|
|
2187
2187
|
<span class="node-label">${this.escapeHtml(s.label)}</span>
|
|
2188
2188
|
</div>
|
|
2189
2189
|
</div>
|
|
@@ -2193,7 +2193,7 @@ class St {
|
|
|
2193
2193
|
<div class="node-card" data-action="goto-target" title="Click to focus on ${this.escapeHtml(t.label)}">
|
|
2194
2194
|
<div class="node-type">Target</div>
|
|
2195
2195
|
<div class="node-card-header">
|
|
2196
|
-
<span class="color-dot" style="background: ${
|
|
2196
|
+
<span class="color-dot" style="background: ${o}; box-shadow: 0 0 8px ${o}80;"></span>
|
|
2197
2197
|
<span class="node-label">${this.escapeHtml(t.label)}</span>
|
|
2198
2198
|
</div>
|
|
2199
2199
|
</div>
|
|
@@ -2281,14 +2281,14 @@ class zt {
|
|
|
2281
2281
|
*/
|
|
2282
2282
|
positionTooltip(e, s) {
|
|
2283
2283
|
if (!this.tooltip) return;
|
|
2284
|
-
const t = this.tooltip.getBoundingClientRect(),
|
|
2284
|
+
const t = this.tooltip.getBoundingClientRect(), i = window.innerWidth, o = window.innerHeight;
|
|
2285
2285
|
let a = e + 15, r = s + 15;
|
|
2286
|
-
a + t.width >
|
|
2286
|
+
a + t.width > i - 10 && (a = e - t.width - 15), r + t.height > o - 10 && (r = s - t.height - 15), a < 10 && (a = 10), r < 10 && (r = 10), this.tooltip.style.left = `${a}px`, this.tooltip.style.top = `${r}px`;
|
|
2287
2287
|
}
|
|
2288
2288
|
/**
|
|
2289
2289
|
* Shows the tooltip with edge info
|
|
2290
2290
|
*/
|
|
2291
|
-
show(e, s, t,
|
|
2291
|
+
show(e, s, t, i, o) {
|
|
2292
2292
|
if (!this.tooltip) return;
|
|
2293
2293
|
const a = e.relationship || "connected to";
|
|
2294
2294
|
this.tooltip.innerHTML = `
|
|
@@ -2303,7 +2303,7 @@ class zt {
|
|
|
2303
2303
|
<span style="font-weight: 600; color: #ff9966;">${this.escapeHtml(t.label)}</span>
|
|
2304
2304
|
</div>
|
|
2305
2305
|
</div>
|
|
2306
|
-
`, this.positionTooltip(
|
|
2306
|
+
`, this.positionTooltip(i, o), this.tooltip.style.opacity = "1", this.tooltip.style.transform = "translateY(0)", this.visible = !0;
|
|
2307
2307
|
}
|
|
2308
2308
|
/**
|
|
2309
2309
|
* Updates tooltip position (called externally on mouse move)
|
|
@@ -2480,25 +2480,25 @@ class kt {
|
|
|
2480
2480
|
this.searchResults.innerHTML = '<div class="f3d-no-results">No results found</div>', this.searchResults.style.display = "block";
|
|
2481
2481
|
return;
|
|
2482
2482
|
}
|
|
2483
|
-
let
|
|
2484
|
-
s.length > 0 && (
|
|
2485
|
-
const a =
|
|
2486
|
-
|
|
2487
|
-
<div class="f3d-search-result-item" data-node-id="${this.escapeHtml(
|
|
2488
|
-
<div class="f3d-result-label">${this.escapeHtml(
|
|
2483
|
+
let i = "";
|
|
2484
|
+
s.length > 0 && (i += '<div class="f3d-search-section-header">Nodes</div>', s.slice(0, 10).forEach((o) => {
|
|
2485
|
+
const a = o.type || "Node";
|
|
2486
|
+
i += `
|
|
2487
|
+
<div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.id)}">
|
|
2488
|
+
<div class="f3d-result-label">${this.escapeHtml(o.label)}</div>
|
|
2489
2489
|
<div class="f3d-result-type">${this.escapeHtml(a)}</div>
|
|
2490
2490
|
</div>
|
|
2491
2491
|
`;
|
|
2492
|
-
}), s.length > 10 && (
|
|
2493
|
-
|
|
2494
|
-
<div class="f3d-search-result-item" data-node-id="${this.escapeHtml(
|
|
2492
|
+
}), s.length > 10 && (i += `<div class="f3d-no-results">+ ${s.length - 10} more nodes</div>`)), t.length > 0 && (i += '<div class="f3d-search-section-header">Relationships</div>', t.slice(0, 5).forEach(({ edge: o, sourceNode: a, targetNode: r }) => {
|
|
2493
|
+
i += `
|
|
2494
|
+
<div class="f3d-search-result-item" data-node-id="${this.escapeHtml(o.source)}">
|
|
2495
2495
|
<div class="f3d-result-label">${this.escapeHtml(a.label)} → ${this.escapeHtml(r.label)}</div>
|
|
2496
|
-
<div class="f3d-result-relationship">${this.escapeHtml(
|
|
2496
|
+
<div class="f3d-result-relationship">${this.escapeHtml(o.relationship || "connected")}</div>
|
|
2497
2497
|
</div>
|
|
2498
2498
|
`;
|
|
2499
|
-
}), t.length > 5 && (
|
|
2500
|
-
|
|
2501
|
-
const a =
|
|
2499
|
+
}), t.length > 5 && (i += `<div class="f3d-no-results">+ ${t.length - 5} more relationships</div>`)), this.searchResults.innerHTML = i, this.searchResults.style.display = "block", this.searchResults.querySelectorAll(".f3d-search-result-item").forEach((o) => {
|
|
2500
|
+
o.addEventListener("click", () => {
|
|
2501
|
+
const a = o.dataset.nodeId;
|
|
2502
2502
|
a && (this.onResultClick(a), this.searchResults && (this.searchResults.style.display = "none"), this.searchInput && this.searchInput.blur());
|
|
2503
2503
|
});
|
|
2504
2504
|
});
|
|
@@ -2656,31 +2656,31 @@ class Lt {
|
|
|
2656
2656
|
setupInteractions() {
|
|
2657
2657
|
this.canvas.addEventListener("wheel", (e) => {
|
|
2658
2658
|
e.preventDefault();
|
|
2659
|
-
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left,
|
|
2660
|
-
this.transform.x = t - (t - this.transform.x) * r, this.transform.y =
|
|
2659
|
+
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = e.deltaY > 0 ? 0.9 : 1.1, a = Math.max(0.1, Math.min(5, this.transform.scale * o)), r = a / this.transform.scale;
|
|
2660
|
+
this.transform.x = t - (t - this.transform.x) * r, this.transform.y = i - (i - this.transform.y) * r, this.transform.scale = a;
|
|
2661
2661
|
}), this.canvas.addEventListener("mousedown", (e) => {
|
|
2662
|
-
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left,
|
|
2662
|
+
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i), a = this.findNodeAt(o.x, o.y);
|
|
2663
2663
|
this.dragStartPos = { x: e.clientX, y: e.clientY }, a ? (this.isDragging = !0, this.draggedNode = a, this.canvas.style.cursor = "grabbing", this.isSimulating = !0) : (this.isPanning = !0, this.canvas.style.cursor = "grabbing"), this.lastMousePos = { x: e.clientX, y: e.clientY };
|
|
2664
2664
|
}), this.canvas.addEventListener("mousemove", (e) => {
|
|
2665
|
-
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left,
|
|
2665
|
+
const s = this.canvas.getBoundingClientRect(), t = e.clientX - s.left, i = e.clientY - s.top, o = this.screenToWorld(t, i);
|
|
2666
2666
|
if (this.isDragging && this.draggedNode)
|
|
2667
|
-
this.draggedNode.x =
|
|
2667
|
+
this.draggedNode.x = o.x, this.draggedNode.y = o.y, this.draggedNode.vx = 0, this.draggedNode.vy = 0;
|
|
2668
2668
|
else if (this.isPanning) {
|
|
2669
2669
|
const a = e.clientX - this.lastMousePos.x, r = e.clientY - this.lastMousePos.y;
|
|
2670
2670
|
this.transform.x += a, this.transform.y += r, this.lastMousePos = { x: e.clientX, y: e.clientY };
|
|
2671
2671
|
} else {
|
|
2672
|
-
const a = this.findNodeAt(
|
|
2672
|
+
const a = this.findNodeAt(o.x, o.y);
|
|
2673
2673
|
if (a !== this.hoveredNode && (this.hoveredNode = a, a ? (this.hoveredEdge && (this.hoveredEdge = null, this.options.onEdgeHover && this.options.onEdgeHover(null)), this.canvas.style.cursor = "pointer", this.options.onNodeHover && this.options.onNodeHover(a.data)) : this.options.onNodeHover && this.options.onNodeHover(null)), !a) {
|
|
2674
|
-
const r = this.findEdgeAt(
|
|
2674
|
+
const r = this.findEdgeAt(o.x, o.y);
|
|
2675
2675
|
r !== this.hoveredEdge && (this.hoveredEdge = r, this.canvas.style.cursor = r ? "pointer" : "grab", this.options.onEdgeHover && this.options.onEdgeHover(r ? r.data : null, e));
|
|
2676
2676
|
}
|
|
2677
2677
|
}
|
|
2678
2678
|
}), this.canvas.addEventListener("mouseup", (e) => {
|
|
2679
|
-
const s = Math.abs(e.clientX - this.dragStartPos.x), t = Math.abs(e.clientY - this.dragStartPos.y),
|
|
2679
|
+
const s = Math.abs(e.clientX - this.dragStartPos.x), t = Math.abs(e.clientY - this.dragStartPos.y), i = s < 5 && t < 5;
|
|
2680
2680
|
if (this.isDragging && this.draggedNode)
|
|
2681
|
-
|
|
2682
|
-
else if (
|
|
2683
|
-
const
|
|
2681
|
+
i && this.options.onNodeClick && (this.selectedNode = this.draggedNode, this.options.onNodeClick(this.draggedNode.data));
|
|
2682
|
+
else if (i) {
|
|
2683
|
+
const o = this.canvas.getBoundingClientRect(), a = this.screenToWorld(e.clientX - o.left, e.clientY - o.top), r = this.findEdgeAt(a.x, a.y);
|
|
2684
2684
|
r && this.options.onEdgeClick && this.options.onEdgeClick(r.data);
|
|
2685
2685
|
}
|
|
2686
2686
|
this.isDragging = !1, this.isPanning = !1, this.draggedNode = null, this.canvas.style.cursor = this.hoveredNode ? "pointer" : "grab";
|
|
@@ -2696,21 +2696,21 @@ class Lt {
|
|
|
2696
2696
|
}
|
|
2697
2697
|
findNodeAt(e, s) {
|
|
2698
2698
|
for (const t of this.nodes.values()) {
|
|
2699
|
-
const
|
|
2700
|
-
if (Math.sqrt(
|
|
2699
|
+
const i = t.x - e, o = t.y - s;
|
|
2700
|
+
if (Math.sqrt(i * i + o * o) < t.radius)
|
|
2701
2701
|
return t;
|
|
2702
2702
|
}
|
|
2703
2703
|
return null;
|
|
2704
2704
|
}
|
|
2705
2705
|
findEdgeAt(e, s) {
|
|
2706
|
-
for (const
|
|
2707
|
-
const
|
|
2708
|
-
if (!
|
|
2709
|
-
const r = a.x -
|
|
2706
|
+
for (const i of this.edges) {
|
|
2707
|
+
const o = this.nodes.get(i.source), a = this.nodes.get(i.target);
|
|
2708
|
+
if (!o || !a) continue;
|
|
2709
|
+
const r = a.x - o.x, c = a.y - o.y, d = r * r + c * c;
|
|
2710
2710
|
if (d === 0) continue;
|
|
2711
|
-
const
|
|
2712
|
-
if (Math.sqrt(
|
|
2713
|
-
return
|
|
2711
|
+
const p = Math.max(0, Math.min(1, ((e - o.x) * r + (s - o.y) * c) / d)), x = o.x + p * r, f = o.y + p * c, u = e - x, y = s - f;
|
|
2712
|
+
if (Math.sqrt(u * u + y * y) < 12)
|
|
2713
|
+
return i;
|
|
2714
2714
|
}
|
|
2715
2715
|
return null;
|
|
2716
2716
|
}
|
|
@@ -2723,87 +2723,87 @@ class Lt {
|
|
|
2723
2723
|
simulate() {
|
|
2724
2724
|
const e = Array.from(this.nodes.values()), s = e.length;
|
|
2725
2725
|
if (s === 0) return;
|
|
2726
|
-
const t = 60,
|
|
2727
|
-
let
|
|
2726
|
+
const t = 60, i = 5;
|
|
2727
|
+
let o = 0;
|
|
2728
2728
|
for (let r = 0; r < s; r++)
|
|
2729
2729
|
for (let c = r + 1; c < s; c++) {
|
|
2730
|
-
const d = e[r],
|
|
2731
|
-
let
|
|
2732
|
-
if (
|
|
2733
|
-
|
|
2734
|
-
const
|
|
2735
|
-
d.vx -=
|
|
2730
|
+
const d = e[r], p = e[c];
|
|
2731
|
+
let x = p.x - d.x, f = p.y - d.y, u = Math.sqrt(x * x + f * f);
|
|
2732
|
+
if (u < t * 3) {
|
|
2733
|
+
u < 1 && (u = 1);
|
|
2734
|
+
const y = this.options.repulsionStrength / (u * u), b = x / u * y, M = f / u * y;
|
|
2735
|
+
d.vx -= b, d.vy -= M, p.vx += b, p.vy += M;
|
|
2736
2736
|
}
|
|
2737
2737
|
}
|
|
2738
2738
|
const a = 80;
|
|
2739
2739
|
for (const r of this.edges) {
|
|
2740
2740
|
const c = this.nodes.get(r.source), d = this.nodes.get(r.target);
|
|
2741
2741
|
if (!c || !d) continue;
|
|
2742
|
-
let
|
|
2743
|
-
|
|
2744
|
-
const
|
|
2745
|
-
c.vx +=
|
|
2742
|
+
let p = d.x - c.x, x = d.y - c.y, f = Math.sqrt(p * p + x * x);
|
|
2743
|
+
f < 1 && (f = 1);
|
|
2744
|
+
const y = (f - a) * this.options.attractionStrength, b = p / f * y, M = x / f * y;
|
|
2745
|
+
c.vx += b, c.vy += M, d.vx -= b, d.vy -= M;
|
|
2746
2746
|
}
|
|
2747
2747
|
for (const r of e) {
|
|
2748
2748
|
if (this.draggedNode === r) continue;
|
|
2749
2749
|
r.vx *= this.options.damping, r.vy *= this.options.damping;
|
|
2750
2750
|
const c = Math.sqrt(r.vx * r.vx + r.vy * r.vy);
|
|
2751
|
-
c >
|
|
2751
|
+
c > i && (r.vx = r.vx / c * i, r.vy = r.vy / c * i), r.x += r.vx, r.y += r.vy, o += r.vx * r.vx + r.vy * r.vy;
|
|
2752
2752
|
}
|
|
2753
|
-
|
|
2753
|
+
o < 0.01 && !this.draggedNode && (this.isSimulating = !1);
|
|
2754
2754
|
}
|
|
2755
2755
|
render() {
|
|
2756
2756
|
const e = this.ctx, s = this.canvas.width / (window.devicePixelRatio || 1), t = this.canvas.height / (window.devicePixelRatio || 1);
|
|
2757
2757
|
e.fillStyle = this.options.backgroundColor, e.fillRect(0, 0, s, t), this.renderGrid(s, t), e.save(), e.translate(this.transform.x, this.transform.y), e.scale(this.transform.scale, this.transform.scale), this.renderEdges(), this.renderNodes(), e.restore();
|
|
2758
2758
|
}
|
|
2759
2759
|
renderGrid(e, s) {
|
|
2760
|
-
const t = this.ctx,
|
|
2760
|
+
const t = this.ctx, i = 40 * this.transform.scale, o = 1.5, a = this.transform.x % i, r = this.transform.y % i;
|
|
2761
2761
|
t.fillStyle = this.options.gridColor;
|
|
2762
|
-
for (let c = a; c < e; c +=
|
|
2763
|
-
for (let d = r; d < s; d +=
|
|
2764
|
-
t.beginPath(), t.arc(c, d,
|
|
2762
|
+
for (let c = a; c < e; c += i)
|
|
2763
|
+
for (let d = r; d < s; d += i)
|
|
2764
|
+
t.beginPath(), t.arc(c, d, o, 0, Math.PI * 2), t.fill();
|
|
2765
2765
|
}
|
|
2766
2766
|
renderEdges() {
|
|
2767
2767
|
const e = this.ctx;
|
|
2768
2768
|
for (const s of this.edges) {
|
|
2769
|
-
const t = this.nodes.get(s.source),
|
|
2770
|
-
if (!t || !
|
|
2771
|
-
const
|
|
2772
|
-
|
|
2769
|
+
const t = this.nodes.get(s.source), i = this.nodes.get(s.target);
|
|
2770
|
+
if (!t || !i) continue;
|
|
2771
|
+
const o = s === this.hoveredEdge, a = e.createLinearGradient(t.x, t.y, i.x, i.y);
|
|
2772
|
+
o ? (a.addColorStop(0, "rgba(255, 153, 102, 0.8)"), a.addColorStop(0.5, "rgba(255, 255, 255, 0.5)"), a.addColorStop(1, "rgba(102, 153, 255, 0.8)"), e.lineWidth = 3) : (a.addColorStop(0, "rgba(255, 153, 102, 0.3)"), a.addColorStop(0.5, "rgba(255, 255, 255, 0.15)"), a.addColorStop(1, "rgba(102, 153, 255, 0.3)"), e.lineWidth = 1.5), e.beginPath(), e.moveTo(t.x, t.y), e.lineTo(i.x, i.y), e.strokeStyle = a, e.stroke();
|
|
2773
2773
|
}
|
|
2774
2774
|
}
|
|
2775
2775
|
renderNodes() {
|
|
2776
2776
|
const e = this.ctx;
|
|
2777
2777
|
for (const s of this.nodes.values()) {
|
|
2778
|
-
const t = s === this.hoveredNode,
|
|
2779
|
-
if (t || o) {
|
|
2780
|
-
const
|
|
2778
|
+
const t = s === this.hoveredNode, i = s === this.selectedNode, o = this.hoveredEdge && (s.data.id === this.hoveredEdge.source || s.data.id === this.hoveredEdge.target), a = s.radius * (t ? 1.1 : 1);
|
|
2779
|
+
if (t || i || o) {
|
|
2780
|
+
const y = e.createRadialGradient(
|
|
2781
2781
|
s.x,
|
|
2782
2782
|
s.y,
|
|
2783
|
-
|
|
2783
|
+
a * 0.5,
|
|
2784
2784
|
s.x,
|
|
2785
2785
|
s.y,
|
|
2786
|
-
|
|
2787
|
-
);
|
|
2788
|
-
|
|
2786
|
+
a * 2
|
|
2787
|
+
), b = t || i ? 0.4 : 0.25;
|
|
2788
|
+
y.addColorStop(0, `rgba(255, 153, 102, ${b})`), y.addColorStop(1, "rgba(255, 153, 102, 0)"), e.fillStyle = y, e.beginPath(), e.arc(s.x, s.y, a * 2, 0, Math.PI * 2), e.fill();
|
|
2789
2789
|
}
|
|
2790
|
-
const
|
|
2791
|
-
s.x -
|
|
2792
|
-
s.y -
|
|
2790
|
+
const r = e.createRadialGradient(
|
|
2791
|
+
s.x - a * 0.3,
|
|
2792
|
+
s.y - a * 0.3,
|
|
2793
2793
|
0,
|
|
2794
2794
|
s.x,
|
|
2795
2795
|
s.y,
|
|
2796
|
-
|
|
2797
|
-
),
|
|
2798
|
-
|
|
2799
|
-
const
|
|
2800
|
-
let
|
|
2801
|
-
if (
|
|
2802
|
-
for (;
|
|
2803
|
-
|
|
2804
|
-
|
|
2796
|
+
a
|
|
2797
|
+
), c = s.color >> 16 & 255, d = s.color >> 8 & 255, p = s.color & 255;
|
|
2798
|
+
r.addColorStop(0, `rgba(${Math.min(255, c + 60)}, ${Math.min(255, d + 60)}, ${Math.min(255, p + 60)}, 0.95)`), r.addColorStop(0.7, `rgba(${c}, ${d}, ${p}, 0.9)`), r.addColorStop(1, `rgba(${Math.max(0, c - 40)}, ${Math.max(0, d - 40)}, ${Math.max(0, p - 40)}, 0.85)`), e.beginPath(), e.arc(s.x, s.y, a, 0, Math.PI * 2), e.fillStyle = r, e.fill(), e.strokeStyle = "rgba(255, 255, 255, 0.2)", e.lineWidth = 1, e.stroke(), e.beginPath(), e.arc(s.x - a * 0.25, s.y - a * 0.25, a * 0.3, 0, Math.PI * 2), e.fillStyle = "rgba(255, 255, 255, 0.15)", e.fill(), e.fillStyle = "white", e.font = "600 11px Inter, -apple-system, BlinkMacSystemFont, sans-serif", e.textAlign = "center", e.textBaseline = "middle";
|
|
2799
|
+
const x = a * 1.6;
|
|
2800
|
+
let f = s.label, u = e.measureText(f).width;
|
|
2801
|
+
if (u > x) {
|
|
2802
|
+
for (; u > x && f.length > 3; )
|
|
2803
|
+
f = f.slice(0, -1), u = e.measureText(f + "...").width;
|
|
2804
|
+
f += "...";
|
|
2805
2805
|
}
|
|
2806
|
-
e.shadowColor = "rgba(0, 0, 0, 0.5)", e.shadowBlur = 3, e.fillText(
|
|
2806
|
+
e.shadowColor = "rgba(0, 0, 0, 0.5)", e.shadowBlur = 3, e.fillText(f, s.x, s.y), e.shadowBlur = 0;
|
|
2807
2807
|
}
|
|
2808
2808
|
}
|
|
2809
2809
|
/**
|
|
@@ -2811,14 +2811,14 @@ class Lt {
|
|
|
2811
2811
|
*/
|
|
2812
2812
|
setData(e) {
|
|
2813
2813
|
this.nodes.clear(), this.edges = [], this.nodeIdToIndex.clear(), e.nodes.forEach((s, t) => {
|
|
2814
|
-
const
|
|
2814
|
+
const i = s.position || {
|
|
2815
2815
|
x: (Math.random() - 0.5) * 300,
|
|
2816
2816
|
y: (Math.random() - 0.5) * 300
|
|
2817
|
-
},
|
|
2817
|
+
}, o = {
|
|
2818
2818
|
id: s.id,
|
|
2819
2819
|
label: s.label,
|
|
2820
|
-
x:
|
|
2821
|
-
y:
|
|
2820
|
+
x: i.x,
|
|
2821
|
+
y: i.y,
|
|
2822
2822
|
vx: 0,
|
|
2823
2823
|
vy: 0,
|
|
2824
2824
|
color: s.color || 16750950,
|
|
@@ -2826,7 +2826,7 @@ class Lt {
|
|
|
2826
2826
|
radius: this.options.nodeRadius,
|
|
2827
2827
|
data: s
|
|
2828
2828
|
};
|
|
2829
|
-
this.nodes.set(s.id,
|
|
2829
|
+
this.nodes.set(s.id, o), this.nodeIdToIndex.set(s.id, t);
|
|
2830
2830
|
}), this.edges = e.edges.map((s) => ({
|
|
2831
2831
|
source: s.source,
|
|
2832
2832
|
target: s.target,
|
|
@@ -2902,9 +2902,9 @@ class Lt {
|
|
|
2902
2902
|
focusOnNode(e) {
|
|
2903
2903
|
const s = this.nodes.get(e);
|
|
2904
2904
|
if (!s) return;
|
|
2905
|
-
const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale,
|
|
2906
|
-
const
|
|
2907
|
-
this.transform.x =
|
|
2905
|
+
const t = this.canvas.width / 2 / (window.devicePixelRatio || 1) - s.x * this.transform.scale, i = this.canvas.height / 2 / (window.devicePixelRatio || 1) - s.y * this.transform.scale, o = this.transform.x, a = this.transform.y, r = 500, c = performance.now(), d = () => {
|
|
2906
|
+
const p = performance.now() - c, x = Math.min(p / r, 1), f = 1 - Math.pow(1 - x, 3);
|
|
2907
|
+
this.transform.x = o + (t - o) * f, this.transform.y = a + (i - a) * f, x < 1 ? requestAnimationFrame(d) : this.selectedNode = s;
|
|
2908
2908
|
};
|
|
2909
2909
|
d();
|
|
2910
2910
|
}
|
|
@@ -2913,8 +2913,8 @@ class Lt {
|
|
|
2913
2913
|
*/
|
|
2914
2914
|
syncFrom3D(e) {
|
|
2915
2915
|
e.forEach((s, t) => {
|
|
2916
|
-
const
|
|
2917
|
-
|
|
2916
|
+
const i = this.nodes.get(t);
|
|
2917
|
+
i && (i.x = s.position.x * 3, i.y = s.position.y * 3, i.vx = 0, i.vy = 0);
|
|
2918
2918
|
}), this.isSimulating = !1;
|
|
2919
2919
|
}
|
|
2920
2920
|
/**
|
|
@@ -3056,8 +3056,8 @@ class Ft {
|
|
|
3056
3056
|
onEdgeHover(e) {
|
|
3057
3057
|
if (e) {
|
|
3058
3058
|
this.edgeManager.highlightEdge(e.edge.source, e.edge.target);
|
|
3059
|
-
const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2,
|
|
3060
|
-
this.edgeTooltipManager.show(e.edge, e.sourceNode, e.targetNode, t,
|
|
3059
|
+
const s = this.container.getBoundingClientRect(), t = s.left + s.width / 2, i = s.top + s.height / 2;
|
|
3060
|
+
this.edgeTooltipManager.show(e.edge, e.sourceNode, e.targetNode, t, i), this.options.onEdgeHover && this.options.onEdgeHover(e.edge, e.sourceNode, e.targetNode), this.emit("edgeHover", e.edge, e.sourceNode, e.targetNode);
|
|
3061
3061
|
} else
|
|
3062
3062
|
this.edgeManager.unhighlightCurrentEdge(), this.edgeTooltipManager.hide(), this.options.onEdgeHover && this.options.onEdgeHover(null, null, null), this.emit("edgeHover", null, null, null);
|
|
3063
3063
|
}
|
|
@@ -3066,7 +3066,7 @@ class Ft {
|
|
|
3066
3066
|
*/
|
|
3067
3067
|
onNodeClick(e) {
|
|
3068
3068
|
this.edgePanelManager.hide();
|
|
3069
|
-
const t = this.edgeManager.getNeighborIds(e.id).map((
|
|
3069
|
+
const t = this.edgeManager.getNeighborIds(e.id).map((i) => this.nodeManager.getNode(i)).filter((i) => i !== void 0);
|
|
3070
3070
|
this.options.showPanel !== !1 && this.panelManager.show(e, t), this.options.onNodeClick && this.options.onNodeClick(e), this.emit("nodeClick", e);
|
|
3071
3071
|
}
|
|
3072
3072
|
/**
|
|
@@ -3170,20 +3170,20 @@ class Ft {
|
|
|
3170
3170
|
* @param fetchFn - Optional fetch function to override the default
|
|
3171
3171
|
*/
|
|
3172
3172
|
async expandNode(e, s = 1, t) {
|
|
3173
|
-
const
|
|
3174
|
-
if (!
|
|
3173
|
+
const i = t ?? this.options.onExpand;
|
|
3174
|
+
if (!i)
|
|
3175
3175
|
return console.warn("[ForceGraph3D] No expand callback provided"), !1;
|
|
3176
3176
|
try {
|
|
3177
|
-
const
|
|
3178
|
-
if (
|
|
3179
|
-
for (const a of
|
|
3177
|
+
const o = await i(e, s);
|
|
3178
|
+
if (o.nodes && Array.isArray(o.nodes))
|
|
3179
|
+
for (const a of o.nodes)
|
|
3180
3180
|
this.addNode(a);
|
|
3181
|
-
if (
|
|
3182
|
-
for (const a of
|
|
3181
|
+
if (o.edges && Array.isArray(o.edges))
|
|
3182
|
+
for (const a of o.edges)
|
|
3183
3183
|
this.addEdge(a);
|
|
3184
|
-
return this.panelManager.hide(), this.emit("expand", e,
|
|
3185
|
-
} catch (
|
|
3186
|
-
return console.error("[ForceGraph3D] Error expanding node:",
|
|
3184
|
+
return this.panelManager.hide(), this.emit("expand", e, o), !0;
|
|
3185
|
+
} catch (o) {
|
|
3186
|
+
return console.error("[ForceGraph3D] Error expanding node:", o), !1;
|
|
3187
3187
|
}
|
|
3188
3188
|
}
|
|
3189
3189
|
/**
|
|
@@ -3230,37 +3230,37 @@ class Ft {
|
|
|
3230
3230
|
console.warn(`[ForceGraph3D] Node "${e}" not found`);
|
|
3231
3231
|
return;
|
|
3232
3232
|
}
|
|
3233
|
-
const
|
|
3234
|
-
x:
|
|
3235
|
-
y:
|
|
3236
|
-
z:
|
|
3237
|
-
}, d = { x:
|
|
3238
|
-
const
|
|
3239
|
-
|
|
3233
|
+
const i = t.position, o = this.sceneManager.camera, a = this.sceneManager.controls, r = o.position.clone().sub(a.target).normalize(), c = {
|
|
3234
|
+
x: i.x + r.x * s,
|
|
3235
|
+
y: i.y + r.y * s,
|
|
3236
|
+
z: i.z + r.z * s
|
|
3237
|
+
}, d = { x: o.position.x, y: o.position.y, z: o.position.z }, p = { x: a.target.x, y: a.target.y, z: a.target.z }, x = 800, f = performance.now(), u = () => {
|
|
3238
|
+
const y = performance.now() - f, b = Math.min(y / x, 1), M = 1 - Math.pow(1 - b, 3);
|
|
3239
|
+
o.position.x = d.x + (c.x - d.x) * M, o.position.y = d.y + (c.y - d.y) * M, o.position.z = d.z + (c.z - d.z) * M, a.target.x = p.x + (i.x - p.x) * M, a.target.y = p.y + (i.y - p.y) * M, a.target.z = p.z + (i.z - p.z) * M, a.update(), b < 1 && requestAnimationFrame(u);
|
|
3240
3240
|
};
|
|
3241
|
-
|
|
3241
|
+
u();
|
|
3242
3242
|
}
|
|
3243
3243
|
/**
|
|
3244
3244
|
* Focuses the camera on an edge (both source and target nodes) with smooth animation
|
|
3245
3245
|
* Camera targets the midpoint and zooms out enough to see both nodes
|
|
3246
3246
|
*/
|
|
3247
3247
|
focusOnEdge(e, s, t = 1.5) {
|
|
3248
|
-
const
|
|
3249
|
-
if (!
|
|
3248
|
+
const i = this.nodeManager.getNode(e), o = this.nodeManager.getNode(s);
|
|
3249
|
+
if (!i || !o) {
|
|
3250
3250
|
console.warn(`[ForceGraph3D] Could not find nodes for edge "${e}" -> "${s}"`);
|
|
3251
3251
|
return;
|
|
3252
3252
|
}
|
|
3253
3253
|
const a = this.sceneManager.camera, r = this.sceneManager.controls, c = {
|
|
3254
|
-
x: (
|
|
3255
|
-
y: (
|
|
3256
|
-
z: (
|
|
3257
|
-
}, d =
|
|
3258
|
-
x: c.x +
|
|
3259
|
-
y: c.y +
|
|
3260
|
-
z: c.z +
|
|
3254
|
+
x: (i.position.x + o.position.x) / 2,
|
|
3255
|
+
y: (i.position.y + o.position.y) / 2,
|
|
3256
|
+
z: (i.position.z + o.position.z) / 2
|
|
3257
|
+
}, d = o.position.x - i.position.x, p = o.position.y - i.position.y, x = o.position.z - i.position.z, f = Math.sqrt(d * d + p * p + x * x), u = Math.max(f * t, 40), y = a.position.clone().sub(r.target).normalize(), b = {
|
|
3258
|
+
x: c.x + y.x * u,
|
|
3259
|
+
y: c.y + y.y * u,
|
|
3260
|
+
z: c.z + y.z * u
|
|
3261
3261
|
}, M = { x: a.position.x, y: a.position.y, z: a.position.z }, N = { x: r.target.x, y: r.target.y, z: r.target.z }, O = 800, L = performance.now(), Y = () => {
|
|
3262
3262
|
const P = performance.now() - L, H = Math.min(P / O, 1), E = 1 - Math.pow(1 - H, 3);
|
|
3263
|
-
a.position.x = M.x + (
|
|
3263
|
+
a.position.x = M.x + (b.x - M.x) * E, a.position.y = M.y + (b.y - M.y) * E, a.position.z = M.z + (b.z - M.z) * E, r.target.x = N.x + (c.x - N.x) * E, r.target.y = N.y + (c.y - N.y) * E, r.target.z = N.z + (c.z - N.z) * E, r.update(), H < 1 && requestAnimationFrame(Y);
|
|
3264
3264
|
};
|
|
3265
3265
|
Y();
|
|
3266
3266
|
}
|
|
@@ -3283,28 +3283,28 @@ class Ft {
|
|
|
3283
3283
|
searchNodes(e) {
|
|
3284
3284
|
if (!e || e.trim() === "")
|
|
3285
3285
|
return [];
|
|
3286
|
-
const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(),
|
|
3287
|
-
return t.forEach((
|
|
3288
|
-
var d,
|
|
3289
|
-
const a = (d =
|
|
3290
|
-
(a || r || c) &&
|
|
3291
|
-
}),
|
|
3286
|
+
const s = e.toLowerCase().trim(), t = this.nodeManager.getAllNodes(), i = [];
|
|
3287
|
+
return t.forEach((o) => {
|
|
3288
|
+
var d, p, x;
|
|
3289
|
+
const a = (d = o.label) == null ? void 0 : d.toLowerCase().includes(s), r = (p = o.id) == null ? void 0 : p.toLowerCase().includes(s), c = (x = o.type) == null ? void 0 : x.toLowerCase().includes(s);
|
|
3290
|
+
(a || r || c) && i.push(o);
|
|
3291
|
+
}), i;
|
|
3292
3292
|
}
|
|
3293
3293
|
/**
|
|
3294
3294
|
* Searches edges by relationship (case-insensitive)
|
|
3295
3295
|
* @returns Array of matching edges with source/target node info
|
|
3296
3296
|
*/
|
|
3297
3297
|
searchEdges(e) {
|
|
3298
|
-
var
|
|
3298
|
+
var o;
|
|
3299
3299
|
if (!e || e.trim() === "")
|
|
3300
3300
|
return [];
|
|
3301
|
-
const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(),
|
|
3301
|
+
const s = e.toLowerCase().trim(), t = this.edgeManager.getAllEdges(), i = [];
|
|
3302
3302
|
for (const a of t)
|
|
3303
|
-
if ((
|
|
3303
|
+
if ((o = a.relationship) == null ? void 0 : o.toLowerCase().includes(s)) {
|
|
3304
3304
|
const c = this.nodeManager.getNode(a.source), d = this.nodeManager.getNode(a.target);
|
|
3305
|
-
c && d &&
|
|
3305
|
+
c && d && i.push({ edge: a, sourceNode: c, targetNode: d });
|
|
3306
3306
|
}
|
|
3307
|
-
return
|
|
3307
|
+
return i;
|
|
3308
3308
|
}
|
|
3309
3309
|
/**
|
|
3310
3310
|
* Gets all nodes as an array
|
|
@@ -3346,11 +3346,11 @@ class Ft {
|
|
|
3346
3346
|
},
|
|
3347
3347
|
onEdgeHover: (s, t) => {
|
|
3348
3348
|
if (s && t) {
|
|
3349
|
-
const
|
|
3350
|
-
|
|
3349
|
+
const i = this.nodeManager.getNode(s.source), o = this.nodeManager.getNode(s.target);
|
|
3350
|
+
i && o && this.edgeTooltipManager.show(
|
|
3351
3351
|
s,
|
|
3352
|
-
o,
|
|
3353
3352
|
i,
|
|
3353
|
+
o,
|
|
3354
3354
|
t.clientX,
|
|
3355
3355
|
t.clientY
|
|
3356
3356
|
);
|
|
@@ -3358,8 +3358,8 @@ class Ft {
|
|
|
3358
3358
|
this.edgeTooltipManager.hide();
|
|
3359
3359
|
},
|
|
3360
3360
|
onEdgeClick: (s) => {
|
|
3361
|
-
const t = this.nodeManager.getNode(s.source),
|
|
3362
|
-
t &&
|
|
3361
|
+
const t = this.nodeManager.getNode(s.source), i = this.nodeManager.getNode(s.target);
|
|
3362
|
+
t && i && this.edgePanelManager.show(s, t, i);
|
|
3363
3363
|
}
|
|
3364
3364
|
}), this.graphData && (this.forceGraph2D.setData(this.graphData), this.forceGraph2D.syncFrom3D(this.nodeManager.getAllNodes())))) : (this.forceGraph2D && this.forceGraph2D.hide(), this.sceneManager.renderer.domElement.style.display = "block", this.rendererManager.start()), this.emit("viewChange", e));
|
|
3365
3365
|
}
|
|
@@ -3374,7 +3374,7 @@ class Ft {
|
|
|
3374
3374
|
*/
|
|
3375
3375
|
emit(e, ...s) {
|
|
3376
3376
|
const t = this.eventCallbacks.get(e);
|
|
3377
|
-
t && t.forEach((
|
|
3377
|
+
t && t.forEach((i) => i(...s));
|
|
3378
3378
|
}
|
|
3379
3379
|
/**
|
|
3380
3380
|
* Sets physics parameters for both 3D and 2D views
|
|
@@ -3451,17 +3451,17 @@ class Ft {
|
|
|
3451
3451
|
`, this.container.appendChild(this.devControls);
|
|
3452
3452
|
const e = this.devControls.querySelector("#dev-repulsion"), s = this.devControls.querySelector("#dev-attraction"), t = this.devControls.querySelector("#dev-damping");
|
|
3453
3453
|
e == null || e.addEventListener("input", () => {
|
|
3454
|
-
const
|
|
3455
|
-
this.setPhysicsParams({ repulsionStrength:
|
|
3454
|
+
const i = parseFloat(e.value);
|
|
3455
|
+
this.setPhysicsParams({ repulsionStrength: i }), this.devControls.querySelector("#dev-repulsion-val").textContent = i.toString();
|
|
3456
3456
|
}), s == null || s.addEventListener("input", () => {
|
|
3457
|
-
const
|
|
3458
|
-
this.setPhysicsParams({ attractionStrength:
|
|
3457
|
+
const i = parseFloat(s.value) / 1e3;
|
|
3458
|
+
this.setPhysicsParams({ attractionStrength: i }), this.devControls.querySelector("#dev-attraction-val").textContent = i.toFixed(3);
|
|
3459
3459
|
}), t == null || t.addEventListener("input", () => {
|
|
3460
|
-
const
|
|
3461
|
-
this.setPhysicsParams({ damping:
|
|
3460
|
+
const i = parseFloat(t.value) / 100;
|
|
3461
|
+
this.setPhysicsParams({ damping: i }), this.devControls.querySelector("#dev-damping-val").textContent = i.toFixed(2);
|
|
3462
3462
|
}), setInterval(() => {
|
|
3463
|
-
const
|
|
3464
|
-
|
|
3463
|
+
const i = this.devControls.querySelector("#dev-node-count"), o = this.devControls.querySelector("#dev-edge-count"), a = this.devControls.querySelector("#dev-fps");
|
|
3464
|
+
i && (i.textContent = this.getNodeCount().toString()), o && (o.textContent = this.getEdgeCount().toString()), a && (a.textContent = this.rendererManager.getFPS().toString());
|
|
3465
3465
|
}, 500);
|
|
3466
3466
|
}
|
|
3467
3467
|
/**
|
|
@@ -3527,12 +3527,12 @@ const Ie = [
|
|
|
3527
3527
|
];
|
|
3528
3528
|
function Ht(h = 30) {
|
|
3529
3529
|
const e = [], s = [];
|
|
3530
|
-
for (let
|
|
3531
|
-
const
|
|
3530
|
+
for (let i = 0; i < h; i++) {
|
|
3531
|
+
const o = i < Ie.length ? Ie[i] : `Node ${i + 1}`;
|
|
3532
3532
|
e.push({
|
|
3533
|
-
id: `node-${
|
|
3534
|
-
label:
|
|
3535
|
-
color: Re[
|
|
3533
|
+
id: `node-${i}`,
|
|
3534
|
+
label: o,
|
|
3535
|
+
color: Re[i % Re.length],
|
|
3536
3536
|
position: {
|
|
3537
3537
|
x: (Math.random() - 0.5) * 60,
|
|
3538
3538
|
y: (Math.random() - 0.5) * 60,
|
|
@@ -3540,22 +3540,22 @@ function Ht(h = 30) {
|
|
|
3540
3540
|
}
|
|
3541
3541
|
});
|
|
3542
3542
|
}
|
|
3543
|
-
for (let
|
|
3544
|
-
const
|
|
3543
|
+
for (let i = 1; i < h; i++) {
|
|
3544
|
+
const o = Math.floor(Math.random() * i);
|
|
3545
3545
|
s.push({
|
|
3546
|
-
source: `node-${
|
|
3547
|
-
target: `node-${
|
|
3546
|
+
source: `node-${i}`,
|
|
3547
|
+
target: `node-${o}`,
|
|
3548
3548
|
relationship: J[Math.floor(Math.random() * J.length)]
|
|
3549
3549
|
});
|
|
3550
3550
|
}
|
|
3551
3551
|
const t = Math.floor(h * 0.5);
|
|
3552
|
-
for (let
|
|
3553
|
-
const
|
|
3552
|
+
for (let i = 0; i < t; i++) {
|
|
3553
|
+
const o = Math.floor(Math.random() * h);
|
|
3554
3554
|
let a = Math.floor(Math.random() * h);
|
|
3555
|
-
|
|
3556
|
-
const r = `node-${
|
|
3555
|
+
o === a && (a = (a + 1) % h);
|
|
3556
|
+
const r = `node-${o}`, c = `node-${a}`;
|
|
3557
3557
|
s.some(
|
|
3558
|
-
(
|
|
3558
|
+
(p) => p.source === r && p.target === c || p.source === c && p.target === r
|
|
3559
3559
|
) || s.push({
|
|
3560
3560
|
source: r,
|
|
3561
3561
|
target: c,
|
|
@@ -3565,18 +3565,18 @@ function Ht(h = 30) {
|
|
|
3565
3565
|
return { nodes: e, edges: s };
|
|
3566
3566
|
}
|
|
3567
3567
|
function Dt(h = 1e3) {
|
|
3568
|
-
const e = [], s = [], t = Math.ceil(h / 50),
|
|
3569
|
-
for (let
|
|
3570
|
-
|
|
3568
|
+
const e = [], s = [], t = Math.ceil(h / 50), i = [];
|
|
3569
|
+
for (let o = 0; o < t; o++)
|
|
3570
|
+
i.push({
|
|
3571
3571
|
x: (Math.random() - 0.5) * 200,
|
|
3572
3572
|
y: (Math.random() - 0.5) * 200,
|
|
3573
3573
|
z: (Math.random() - 0.5) * 200
|
|
3574
3574
|
});
|
|
3575
|
-
for (let
|
|
3576
|
-
const a = o
|
|
3575
|
+
for (let o = 0; o < h; o++) {
|
|
3576
|
+
const a = i[o % t];
|
|
3577
3577
|
e.push({
|
|
3578
|
-
id: `node-${
|
|
3579
|
-
label: `N${
|
|
3578
|
+
id: `node-${o}`,
|
|
3579
|
+
label: `N${o}`,
|
|
3580
3580
|
position: {
|
|
3581
3581
|
x: a.x + (Math.random() - 0.5) * 40,
|
|
3582
3582
|
y: a.y + (Math.random() - 0.5) * 40,
|
|
@@ -3584,16 +3584,16 @@ function Dt(h = 1e3) {
|
|
|
3584
3584
|
}
|
|
3585
3585
|
});
|
|
3586
3586
|
}
|
|
3587
|
-
for (let
|
|
3588
|
-
const a = Math.floor(
|
|
3587
|
+
for (let o = 1; o < h; o++) {
|
|
3588
|
+
const a = Math.floor(o / 50) * 50, r = a === 0 ? Math.floor(Math.random() * o) : a + Math.floor(Math.random() * Math.min(o - a, 50));
|
|
3589
3589
|
s.push({
|
|
3590
|
-
source: `node-${
|
|
3591
|
-
target: `node-${Math.min(r,
|
|
3590
|
+
source: `node-${o}`,
|
|
3591
|
+
target: `node-${Math.min(r, o - 1)}`,
|
|
3592
3592
|
relationship: "links to"
|
|
3593
3593
|
});
|
|
3594
3594
|
}
|
|
3595
|
-
for (let
|
|
3596
|
-
const a =
|
|
3595
|
+
for (let o = 1; o < t; o++) {
|
|
3596
|
+
const a = o * 50, r = (o - 1) * 50 + Math.floor(Math.random() * 50);
|
|
3597
3597
|
s.push({
|
|
3598
3598
|
source: `node-${a}`,
|
|
3599
3599
|
target: `node-${r}`,
|