@cocorof/graphier 1.4.3 → 1.4.5
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/index.cjs +107 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +107 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -185,6 +185,13 @@ export declare interface NavigationConfig {
|
|
|
185
185
|
* (default: cameraMode in 3D, "pan" in 2D)
|
|
186
186
|
*/
|
|
187
187
|
keyboard?: "fly" | "orbit" | "pan" | "off";
|
|
188
|
+
/**
|
|
189
|
+
* Base drag-pan speed multiplier (default: 1 = cursor-accurate at the
|
|
190
|
+
* orbit-target depth). On top of this, pan automatically accelerates
|
|
191
|
+
* up to 3x as the camera zooms deep into the graph — otherwise
|
|
192
|
+
* traversing a large graph while zoomed in takes dozens of drags.
|
|
193
|
+
*/
|
|
194
|
+
panSpeed?: number;
|
|
188
195
|
}
|
|
189
196
|
|
|
190
197
|
export declare const neon: ThemeConfig;
|
package/dist/index.js
CHANGED
|
@@ -2050,7 +2050,7 @@ function createPanUpdate(camera, controls, keys) {
|
|
|
2050
2050
|
const target = controls.target;
|
|
2051
2051
|
const dist = camera.position.distanceTo(target);
|
|
2052
2052
|
if (dx || dy) {
|
|
2053
|
-
const step = Math.max(dist, 50) * PAN_SPEED;
|
|
2053
|
+
const step = Math.max(dist, 50) * PAN_SPEED * (controls.panSpeed || 1);
|
|
2054
2054
|
_panRight.setFromMatrixColumn(camera.matrix, 0);
|
|
2055
2055
|
_panUp.setFromMatrixColumn(camera.matrix, 1);
|
|
2056
2056
|
_panOffset.set(0, 0, 0).addScaledVector(_panRight, dx * step).addScaledVector(_panUp, dy * step);
|
|
@@ -2229,6 +2229,7 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2229
2229
|
controls.zoomSpeed = 1.2;
|
|
2230
2230
|
controls.minDistance = 10;
|
|
2231
2231
|
controls.maxDistance = 3e4;
|
|
2232
|
+
controls.screenSpacePanning = true;
|
|
2232
2233
|
scene.add(new THREE.AmbientLight(16777215, 0.8));
|
|
2233
2234
|
const stars = createStarField(4e3, 8e3);
|
|
2234
2235
|
stars.visible = style.starField;
|
|
@@ -2242,26 +2243,35 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2242
2243
|
controls.enableZoom = false;
|
|
2243
2244
|
const flags = {
|
|
2244
2245
|
is2D: false,
|
|
2245
|
-
keyboardMode3D: cameraMode
|
|
2246
|
+
keyboardMode3D: cameraMode,
|
|
2247
|
+
rotateButton: null,
|
|
2248
|
+
panSpeedBase: 1
|
|
2246
2249
|
};
|
|
2247
|
-
const
|
|
2250
|
+
const _wheelOffset = new THREE.Vector3();
|
|
2248
2251
|
const onWheel = (e) => {
|
|
2249
2252
|
if (flags.is2D) return;
|
|
2250
2253
|
e.preventDefault();
|
|
2251
2254
|
let delta = -e.deltaY;
|
|
2252
2255
|
if (e.deltaMode === 1) delta *= 40;
|
|
2253
2256
|
if (e.deltaMode === 2) delta *= 800;
|
|
2254
|
-
|
|
2255
|
-
|
|
2257
|
+
const target = controls.target;
|
|
2258
|
+
_wheelOffset.copy(camera.position).sub(target);
|
|
2259
|
+
const dist = _wheelOffset.length();
|
|
2256
2260
|
const moveAmount = delta * 2e-3 * Math.max(dist * 0.1, 1);
|
|
2257
|
-
|
|
2258
|
-
|
|
2261
|
+
const newDist = Math.min(
|
|
2262
|
+
Math.max(dist - moveAmount, controls.minDistance),
|
|
2263
|
+
controls.maxDistance
|
|
2264
|
+
);
|
|
2265
|
+
_wheelOffset.setLength(newDist);
|
|
2266
|
+
camera.position.copy(target).add(_wheelOffset);
|
|
2259
2267
|
};
|
|
2260
2268
|
canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
2269
|
+
const trackballCleanup = setupTrackballRotation(canvas, camera, controls, flags);
|
|
2261
2270
|
const scrollCleanup = () => {
|
|
2262
2271
|
canvas.removeEventListener("wheel", onWheel);
|
|
2263
2272
|
canvas.removeEventListener("dragstart", onDragStart);
|
|
2264
2273
|
canvas.removeEventListener("selectstart", onSelectStart);
|
|
2274
|
+
trackballCleanup();
|
|
2265
2275
|
};
|
|
2266
2276
|
return {
|
|
2267
2277
|
scene,
|
|
@@ -2278,24 +2288,82 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2278
2288
|
flags
|
|
2279
2289
|
};
|
|
2280
2290
|
}
|
|
2281
|
-
const
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2291
|
+
const TRACKBALL_SPEED = 4e-3;
|
|
2292
|
+
function setupTrackballRotation(canvas, camera, controls, flags) {
|
|
2293
|
+
let rotating = false;
|
|
2294
|
+
let lastX = 0;
|
|
2295
|
+
let lastY = 0;
|
|
2296
|
+
const _offset2 = new THREE.Vector3();
|
|
2297
|
+
const _right2 = new THREE.Vector3();
|
|
2298
|
+
const _upAxis = new THREE.Vector3();
|
|
2299
|
+
const _q2 = new THREE.Quaternion();
|
|
2300
|
+
const _qPitch = new THREE.Quaternion();
|
|
2301
|
+
function onDown(e) {
|
|
2302
|
+
if (flags.rotateButton == null || e.button !== flags.rotateButton) return;
|
|
2303
|
+
rotating = true;
|
|
2304
|
+
lastX = e.clientX;
|
|
2305
|
+
lastY = e.clientY;
|
|
2306
|
+
try {
|
|
2307
|
+
canvas.setPointerCapture(e.pointerId);
|
|
2308
|
+
} catch {
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
function onMove(e) {
|
|
2312
|
+
if (!rotating) return;
|
|
2313
|
+
const dx = e.clientX - lastX;
|
|
2314
|
+
const dy = e.clientY - lastY;
|
|
2315
|
+
lastX = e.clientX;
|
|
2316
|
+
lastY = e.clientY;
|
|
2317
|
+
if (!dx && !dy) return;
|
|
2318
|
+
const target = controls.target;
|
|
2319
|
+
_offset2.copy(camera.position).sub(target);
|
|
2320
|
+
_right2.setFromMatrixColumn(camera.matrix, 0);
|
|
2321
|
+
_upAxis.setFromMatrixColumn(camera.matrix, 1);
|
|
2322
|
+
_q2.setFromAxisAngle(_upAxis, -dx * TRACKBALL_SPEED);
|
|
2323
|
+
_qPitch.setFromAxisAngle(_right2, -dy * TRACKBALL_SPEED);
|
|
2324
|
+
_q2.multiply(_qPitch);
|
|
2325
|
+
_offset2.applyQuaternion(_q2);
|
|
2326
|
+
camera.up.applyQuaternion(_q2).normalize();
|
|
2327
|
+
camera.position.copy(target).add(_offset2);
|
|
2328
|
+
camera.lookAt(target);
|
|
2329
|
+
}
|
|
2330
|
+
function onUp(e) {
|
|
2331
|
+
if (!rotating) return;
|
|
2332
|
+
rotating = false;
|
|
2333
|
+
try {
|
|
2334
|
+
canvas.releasePointerCapture(e.pointerId);
|
|
2335
|
+
} catch {
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
canvas.addEventListener("pointerdown", onDown);
|
|
2339
|
+
canvas.addEventListener("pointermove", onMove);
|
|
2340
|
+
canvas.addEventListener("pointerup", onUp);
|
|
2341
|
+
canvas.addEventListener("pointercancel", onUp);
|
|
2342
|
+
return () => {
|
|
2343
|
+
canvas.removeEventListener("pointerdown", onDown);
|
|
2344
|
+
canvas.removeEventListener("pointermove", onMove);
|
|
2345
|
+
canvas.removeEventListener("pointerup", onUp);
|
|
2346
|
+
canvas.removeEventListener("pointercancel", onUp);
|
|
2347
|
+
};
|
|
2348
|
+
}
|
|
2285
2349
|
function applyNavigationMode(state, is2D, nav) {
|
|
2286
2350
|
const { controls, camera, keyboard } = state;
|
|
2287
2351
|
state.flags.is2D = is2D;
|
|
2288
2352
|
const left = (nav == null ? void 0 : nav.leftButton) ?? (is2D ? "pan" : "rotate");
|
|
2289
2353
|
const right = (nav == null ? void 0 : nav.rightButton) ?? (is2D ? "rotate" : "pan");
|
|
2354
|
+
const NONE = -1;
|
|
2290
2355
|
controls.mouseButtons = {
|
|
2291
|
-
LEFT:
|
|
2356
|
+
LEFT: left === "pan" ? THREE.MOUSE.PAN : NONE,
|
|
2292
2357
|
MIDDLE: THREE.MOUSE.DOLLY,
|
|
2293
|
-
RIGHT:
|
|
2358
|
+
RIGHT: right === "pan" ? THREE.MOUSE.PAN : NONE
|
|
2294
2359
|
};
|
|
2295
|
-
controls.enableRotate =
|
|
2360
|
+
controls.enableRotate = false;
|
|
2361
|
+
state.flags.rotateButton = left === "rotate" ? 0 : right === "rotate" ? 2 : null;
|
|
2296
2362
|
controls.touches = left === "pan" ? { ONE: THREE.TOUCH.PAN, TWO: THREE.TOUCH.DOLLY_PAN } : { ONE: THREE.TOUCH.ROTATE, TWO: THREE.TOUCH.DOLLY_PAN };
|
|
2297
2363
|
controls.enableZoom = is2D;
|
|
2298
|
-
controls.screenSpacePanning =
|
|
2364
|
+
controls.screenSpacePanning = true;
|
|
2365
|
+
state.flags.panSpeedBase = (nav == null ? void 0 : nav.panSpeed) ?? 1;
|
|
2366
|
+
controls.panSpeed = state.flags.panSpeedBase;
|
|
2299
2367
|
const kb = (nav == null ? void 0 : nav.keyboard) ?? (is2D ? "pan" : state.flags.keyboardMode3D);
|
|
2300
2368
|
if (kb === "off") {
|
|
2301
2369
|
keyboard.setEnabled(false);
|
|
@@ -2631,6 +2699,7 @@ function animateCamera(camera, controls, targetPos, targetLookAt, duration) {
|
|
|
2631
2699
|
function zoomToFitPositions(camera, controls, positions, duration, padding) {
|
|
2632
2700
|
const count = positions.length / 3;
|
|
2633
2701
|
if (count === 0) return;
|
|
2702
|
+
camera.up.set(0, 1, 0);
|
|
2634
2703
|
let cx = 0, cy = 0, cz = 0;
|
|
2635
2704
|
for (let i = 0; i < count; i++) {
|
|
2636
2705
|
cx += positions[i * 3];
|
|
@@ -2875,8 +2944,8 @@ function setupInteraction(canvas, camera, controls, getNodesMesh, getNodes, call
|
|
|
2875
2944
|
}
|
|
2876
2945
|
}
|
|
2877
2946
|
function onContextMenu2(e) {
|
|
2878
|
-
if (!callbacks.onContextMenu) return;
|
|
2879
2947
|
e.preventDefault();
|
|
2948
|
+
if (!callbacks.onContextMenu) return;
|
|
2880
2949
|
const nodesMesh = getNodesMesh();
|
|
2881
2950
|
if (!nodesMesh) return;
|
|
2882
2951
|
const rect = canvas.getBoundingClientRect();
|
|
@@ -3140,7 +3209,29 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3140
3209
|
rendererProp
|
|
3141
3210
|
);
|
|
3142
3211
|
sceneRef.current = state;
|
|
3212
|
+
let panBoostAt = 0;
|
|
3213
|
+
let graphRadius = 0;
|
|
3143
3214
|
const cancelAnim = startAnimationLoop(state, () => {
|
|
3215
|
+
const nowMs = performance.now();
|
|
3216
|
+
if (nowMs - panBoostAt > 400) {
|
|
3217
|
+
panBoostAt = nowMs;
|
|
3218
|
+
const pos = dataRef.current.positions;
|
|
3219
|
+
if (pos) {
|
|
3220
|
+
let maxSq = 0;
|
|
3221
|
+
for (let i = 0; i < pos.length; i += 3) {
|
|
3222
|
+
const sq = pos[i] * pos[i] + pos[i + 1] * pos[i + 1] + pos[i + 2] * pos[i + 2];
|
|
3223
|
+
if (sq > maxSq) maxSq = sq;
|
|
3224
|
+
}
|
|
3225
|
+
graphRadius = Math.sqrt(maxSq);
|
|
3226
|
+
}
|
|
3227
|
+
if (graphRadius > 0) {
|
|
3228
|
+
const dist = state.camera.position.distanceTo(
|
|
3229
|
+
state.controls.target
|
|
3230
|
+
);
|
|
3231
|
+
const boost = Math.min(3, Math.max(1, graphRadius / (3 * dist)));
|
|
3232
|
+
state.controls.panSpeed = state.flags.panSpeedBase * boost;
|
|
3233
|
+
}
|
|
3234
|
+
}
|
|
3144
3235
|
updateLabels(
|
|
3145
3236
|
state.labels,
|
|
3146
3237
|
dataRef.current.nodes,
|