@cocorof/graphier 1.1.1 → 1.3.0
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 +115 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +14 -0
- package/dist/index.js +115 -73
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -34,7 +34,8 @@ const DEFAULT_STYLE = {
|
|
|
34
34
|
labelThreshold: 0.8,
|
|
35
35
|
showLabels: true,
|
|
36
36
|
maxLabels: 150,
|
|
37
|
-
edgeWidthScale: 1
|
|
37
|
+
edgeWidthScale: 1,
|
|
38
|
+
flySpeed: 1
|
|
38
39
|
};
|
|
39
40
|
const DEFAULT_LAYOUT = {
|
|
40
41
|
type: "force-3d",
|
|
@@ -42,7 +43,8 @@ const DEFAULT_LAYOUT = {
|
|
|
42
43
|
linkDistance: "auto",
|
|
43
44
|
alphaDecay: "auto",
|
|
44
45
|
velocityDecay: 0.4,
|
|
45
|
-
settledThreshold: 5e-3
|
|
46
|
+
settledThreshold: 5e-3,
|
|
47
|
+
spreadFactor: "auto"
|
|
46
48
|
};
|
|
47
49
|
function hexToRgb(hex) {
|
|
48
50
|
const c2 = hex.replace("#", "");
|
|
@@ -50,8 +52,8 @@ function hexToRgb(hex) {
|
|
|
50
52
|
return [(n >> 16) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
|
|
51
53
|
}
|
|
52
54
|
function rgbToHex(r, g, b) {
|
|
53
|
-
const
|
|
54
|
-
const hex =
|
|
55
|
+
const clamp = (v) => Math.round(Math.max(0, Math.min(1, v)) * 255);
|
|
56
|
+
const hex = clamp(r) << 16 | clamp(g) << 8 | clamp(b);
|
|
55
57
|
return "#" + hex.toString(16).padStart(6, "0");
|
|
56
58
|
}
|
|
57
59
|
function brighten(hex, factor) {
|
|
@@ -188,17 +190,26 @@ function resolveTheme(theme) {
|
|
|
188
190
|
}
|
|
189
191
|
return { nodeColor, nodeColorBright, linkColor, backgroundColor };
|
|
190
192
|
}
|
|
193
|
+
function autoSpreadFactor(n) {
|
|
194
|
+
if (n <= 500) return 1;
|
|
195
|
+
if (n <= 2e3) return 1 + (n - 500) / 1500 * 0.3;
|
|
196
|
+
if (n <= 1e4) return 1.3 + (n - 2e3) / 8e3 * 0.5;
|
|
197
|
+
return Math.min(2.5, 1.8 + (n - 1e4) / 4e4 * 0.7);
|
|
198
|
+
}
|
|
191
199
|
function resolveLayoutParams(nodeCount, config) {
|
|
192
200
|
const n = nodeCount;
|
|
193
|
-
const
|
|
194
|
-
const
|
|
201
|
+
const spread = (config == null ? void 0 : config.spreadFactor) !== "auto" && (config == null ? void 0 : config.spreadFactor) != null ? config.spreadFactor : autoSpreadFactor(n);
|
|
202
|
+
const baseCharge = (config == null ? void 0 : config.charge) !== "auto" && (config == null ? void 0 : config.charge) != null ? config.charge : n > 5e4 ? -80 : n > 1e4 ? -120 : -200;
|
|
203
|
+
const charge = baseCharge * spread;
|
|
204
|
+
const distanceMax = (n > 5e4 ? 1500 : n > 1e4 ? 2e3 : 3e3) * spread;
|
|
195
205
|
const theta = n > 2e4 ? 1.5 : n > 5e3 ? 1.2 : 0.9;
|
|
196
|
-
const
|
|
206
|
+
const baseLinkDistance = (config == null ? void 0 : config.linkDistance) !== "auto" && (config == null ? void 0 : config.linkDistance) != null ? config.linkDistance : n > 5e4 ? 120 : n > 1e4 ? 180 : 250;
|
|
207
|
+
const linkDistance = baseLinkDistance * spread;
|
|
197
208
|
const alphaDecay = (config == null ? void 0 : config.alphaDecay) !== "auto" && (config == null ? void 0 : config.alphaDecay) != null ? config.alphaDecay : n > 5e4 ? 0.04 : n > 1e4 ? 0.03 : 0.02;
|
|
198
209
|
const velocityDecay = (config == null ? void 0 : config.velocityDecay) ?? 0.4;
|
|
199
210
|
const settledThreshold = (config == null ? void 0 : config.settledThreshold) ?? 5e-3;
|
|
200
211
|
const postEvery = n > 5e4 ? 5 : n > 1e4 ? 3 : 2;
|
|
201
|
-
const initialRadius2 = 500 + Math.min(n, 1e4) * 0.1;
|
|
212
|
+
const initialRadius2 = (500 + Math.min(n, 1e4) * 0.1) * spread;
|
|
202
213
|
return {
|
|
203
214
|
charge,
|
|
204
215
|
distanceMax,
|
|
@@ -1961,60 +1972,45 @@ function disposeLabelSystem(state) {
|
|
|
1961
1972
|
}
|
|
1962
1973
|
state.textureCache.clear();
|
|
1963
1974
|
}
|
|
1964
|
-
const
|
|
1965
|
-
const ORBIT_MAX_SPEED = 0.06;
|
|
1966
|
-
const ORBIT_DAMPING = 0.88;
|
|
1975
|
+
const ORBIT_ROTATE_SPEED = 0.02;
|
|
1967
1976
|
const ORBIT_ZOOM_FACTOR = 0.015;
|
|
1968
|
-
const
|
|
1969
|
-
const FLY_ACCEL = 6e-3;
|
|
1970
|
-
const FLY_FRICTION = 0.92;
|
|
1971
|
-
const FLY_MAX_THRUST = 0.18;
|
|
1977
|
+
const FLY_THRUST_SPEED = 0.08;
|
|
1972
1978
|
const FLY_TURN_RATE = 8e-3;
|
|
1973
|
-
const FLY_DEAD_ZONE = 2e-4;
|
|
1974
1979
|
const _offset = new THREE__namespace.Vector3();
|
|
1975
1980
|
const _right = new THREE__namespace.Vector3();
|
|
1976
1981
|
const _q = new THREE__namespace.Quaternion();
|
|
1977
1982
|
const _dir = new THREE__namespace.Vector3();
|
|
1978
|
-
|
|
1979
|
-
return v < min ? min : v > max ? max : v;
|
|
1980
|
-
}
|
|
1983
|
+
const _worldUp = new THREE__namespace.Vector3(0, 1, 0);
|
|
1981
1984
|
function createOrbitUpdate(camera, controls, keys) {
|
|
1982
|
-
const vel = { zoom: 0, azimuth: 0, polar: 0 };
|
|
1983
1985
|
return function update() {
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
if (keys["
|
|
1988
|
-
if (keys["
|
|
1989
|
-
if (keys["
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
vel.azimuth *= ORBIT_DAMPING;
|
|
1995
|
-
vel.polar *= ORBIT_DAMPING;
|
|
1996
|
-
if (Math.abs(vel.zoom) < ORBIT_DEAD_ZONE) vel.zoom = 0;
|
|
1997
|
-
if (Math.abs(vel.azimuth) < ORBIT_DEAD_ZONE) vel.azimuth = 0;
|
|
1998
|
-
if (Math.abs(vel.polar) < ORBIT_DEAD_ZONE) vel.polar = 0;
|
|
1999
|
-
const hasMotion = vel.zoom !== 0 || vel.azimuth !== 0 || vel.polar !== 0;
|
|
1986
|
+
let zoom = 0;
|
|
1987
|
+
let azimuth = 0;
|
|
1988
|
+
let polar = 0;
|
|
1989
|
+
if (keys["z"] || keys["Z"]) zoom -= ORBIT_ROTATE_SPEED;
|
|
1990
|
+
if (keys["x"] || keys["X"]) zoom += ORBIT_ROTATE_SPEED;
|
|
1991
|
+
if (keys["ArrowLeft"]) azimuth -= ORBIT_ROTATE_SPEED;
|
|
1992
|
+
if (keys["ArrowRight"]) azimuth += ORBIT_ROTATE_SPEED;
|
|
1993
|
+
if (keys["ArrowUp"]) polar -= ORBIT_ROTATE_SPEED;
|
|
1994
|
+
if (keys["ArrowDown"]) polar += ORBIT_ROTATE_SPEED;
|
|
1995
|
+
const hasMotion = zoom !== 0 || azimuth !== 0 || polar !== 0;
|
|
2000
1996
|
if (!hasMotion) return false;
|
|
2001
1997
|
const target = controls.target;
|
|
2002
1998
|
_offset.copy(camera.position).sub(target);
|
|
2003
1999
|
let radius = _offset.length();
|
|
2004
|
-
if (
|
|
2005
|
-
radius *= 1 +
|
|
2000
|
+
if (zoom !== 0) {
|
|
2001
|
+
radius *= 1 + zoom * ORBIT_ZOOM_FACTOR * radius * 0.01;
|
|
2006
2002
|
radius = Math.max(controls.minDistance, Math.min(controls.maxDistance, radius));
|
|
2007
2003
|
}
|
|
2008
|
-
if (
|
|
2009
|
-
_q.setFromAxisAngle(camera.up, -
|
|
2004
|
+
if (azimuth !== 0) {
|
|
2005
|
+
_q.setFromAxisAngle(camera.up, -azimuth);
|
|
2010
2006
|
_offset.applyQuaternion(_q);
|
|
2011
2007
|
}
|
|
2012
|
-
if (
|
|
2008
|
+
if (polar !== 0) {
|
|
2013
2009
|
_right.copy(_offset).normalize().cross(camera.up).normalize();
|
|
2014
2010
|
if (_right.lengthSq() < 1e-3) {
|
|
2015
2011
|
_right.setFromMatrixColumn(camera.matrixWorld, 0);
|
|
2016
2012
|
}
|
|
2017
|
-
_q.setFromAxisAngle(_right,
|
|
2013
|
+
_q.setFromAxisAngle(_right, polar);
|
|
2018
2014
|
_offset.applyQuaternion(_q);
|
|
2019
2015
|
camera.up.applyQuaternion(_q).normalize();
|
|
2020
2016
|
}
|
|
@@ -2025,48 +2021,47 @@ function createOrbitUpdate(camera, controls, keys) {
|
|
|
2025
2021
|
return true;
|
|
2026
2022
|
};
|
|
2027
2023
|
}
|
|
2028
|
-
function createFlyUpdate(camera, controls, keys) {
|
|
2029
|
-
const vel = { thrust: 0, yaw: 0, pitch: 0 };
|
|
2024
|
+
function createFlyUpdate(camera, controls, keys, state) {
|
|
2030
2025
|
return function update() {
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
if (keys["
|
|
2036
|
-
if (keys["
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
vel.thrust *= FLY_FRICTION;
|
|
2043
|
-
vel.yaw *= FLY_FRICTION;
|
|
2044
|
-
vel.pitch *= FLY_FRICTION;
|
|
2045
|
-
if (Math.abs(vel.thrust) < FLY_DEAD_ZONE) vel.thrust = 0;
|
|
2046
|
-
if (Math.abs(vel.yaw) < FLY_DEAD_ZONE) vel.yaw = 0;
|
|
2047
|
-
if (Math.abs(vel.pitch) < FLY_DEAD_ZONE) vel.pitch = 0;
|
|
2048
|
-
const hasMotion = vel.thrust !== 0 || vel.yaw !== 0 || vel.pitch !== 0;
|
|
2026
|
+
const speedMul = state.flySpeed;
|
|
2027
|
+
let thrust = 0;
|
|
2028
|
+
let yaw = 0;
|
|
2029
|
+
let pitch = 0;
|
|
2030
|
+
if (keys["z"] || keys["Z"]) thrust += FLY_THRUST_SPEED * speedMul;
|
|
2031
|
+
if (keys["x"] || keys["X"]) thrust -= FLY_THRUST_SPEED * speedMul;
|
|
2032
|
+
if (keys["a"] || keys["A"] || keys["ArrowLeft"]) yaw += FLY_TURN_RATE;
|
|
2033
|
+
if (keys["d"] || keys["D"] || keys["ArrowRight"]) yaw -= FLY_TURN_RATE;
|
|
2034
|
+
if (keys["w"] || keys["W"] || keys["ArrowUp"]) pitch += FLY_TURN_RATE;
|
|
2035
|
+
if (keys["s"] || keys["S"] || keys["ArrowDown"]) pitch -= FLY_TURN_RATE;
|
|
2036
|
+
const hasMotion = thrust !== 0 || yaw !== 0 || pitch !== 0;
|
|
2049
2037
|
if (!hasMotion) return false;
|
|
2050
|
-
if (
|
|
2051
|
-
|
|
2038
|
+
if (yaw !== 0) {
|
|
2039
|
+
const upDot = camera.up.dot(_worldUp);
|
|
2040
|
+
const yawSign = upDot < 0 ? -1 : 1;
|
|
2041
|
+
_q.setFromAxisAngle(_worldUp, yaw * yawSign);
|
|
2052
2042
|
camera.quaternion.premultiply(_q);
|
|
2043
|
+
camera.up.applyQuaternion(_q).normalize();
|
|
2053
2044
|
}
|
|
2054
|
-
if (
|
|
2045
|
+
if (pitch !== 0) {
|
|
2055
2046
|
_right.setFromMatrixColumn(camera.matrixWorld, 0).normalize();
|
|
2056
|
-
_q.setFromAxisAngle(_right,
|
|
2047
|
+
_q.setFromAxisAngle(_right, pitch);
|
|
2057
2048
|
camera.quaternion.premultiply(_q);
|
|
2049
|
+
camera.up.applyQuaternion(_q).normalize();
|
|
2058
2050
|
}
|
|
2059
|
-
if (
|
|
2051
|
+
if (thrust !== 0) {
|
|
2052
|
+
const lookDist = camera.position.distanceTo(controls.target);
|
|
2053
|
+
const distScale = Math.max(0.3, lookDist * 3e-3);
|
|
2060
2054
|
camera.getWorldDirection(_dir);
|
|
2061
|
-
_dir.multiplyScalar(
|
|
2055
|
+
_dir.multiplyScalar(thrust * distScale * 100);
|
|
2062
2056
|
camera.position.add(_dir);
|
|
2063
2057
|
controls.target.add(_dir);
|
|
2064
2058
|
}
|
|
2065
2059
|
return true;
|
|
2066
2060
|
};
|
|
2067
2061
|
}
|
|
2068
|
-
function setupKeyboardControls(camera, controls, container, mode = "fly") {
|
|
2062
|
+
function setupKeyboardControls(camera, controls, container, mode = "fly", flySpeed = 1) {
|
|
2069
2063
|
const keys = {};
|
|
2064
|
+
const state = { flySpeed };
|
|
2070
2065
|
function onKeyDown2(e) {
|
|
2071
2066
|
var _a;
|
|
2072
2067
|
const tag = (_a = e.target) == null ? void 0 : _a.tagName;
|
|
@@ -2082,13 +2077,16 @@ function setupKeyboardControls(camera, controls, container, mode = "fly") {
|
|
|
2082
2077
|
container.addEventListener("keydown", onKeyDown2);
|
|
2083
2078
|
container.addEventListener("keyup", onKeyUp);
|
|
2084
2079
|
container.addEventListener("blur", onBlur);
|
|
2085
|
-
const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys) : createOrbitUpdate(camera, controls, keys);
|
|
2080
|
+
const updateFn = mode === "fly" ? createFlyUpdate(camera, controls, keys, state) : createOrbitUpdate(camera, controls, keys);
|
|
2086
2081
|
function cleanup() {
|
|
2087
2082
|
container.removeEventListener("keydown", onKeyDown2);
|
|
2088
2083
|
container.removeEventListener("keyup", onKeyUp);
|
|
2089
2084
|
container.removeEventListener("blur", onBlur);
|
|
2090
2085
|
}
|
|
2091
|
-
|
|
2086
|
+
function setFlySpeed(speed) {
|
|
2087
|
+
state.flySpeed = speed;
|
|
2088
|
+
}
|
|
2089
|
+
return { update: updateFn, cleanup, setFlySpeed };
|
|
2092
2090
|
}
|
|
2093
2091
|
function createScene(container, backgroundColor, style, rendererConfig) {
|
|
2094
2092
|
const scene = new THREE__namespace.Scene();
|
|
@@ -2126,7 +2124,22 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2126
2124
|
const labels = createLabelSystem(style.maxLabels);
|
|
2127
2125
|
scene.add(labels.group);
|
|
2128
2126
|
const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
|
|
2129
|
-
const keyboard = setupKeyboardControls(camera, controls, container, cameraMode);
|
|
2127
|
+
const keyboard = setupKeyboardControls(camera, controls, container, cameraMode, style.flySpeed ?? 1);
|
|
2128
|
+
controls.enableZoom = false;
|
|
2129
|
+
const _wheelDir = new THREE__namespace.Vector3();
|
|
2130
|
+
const onWheel = (e) => {
|
|
2131
|
+
e.preventDefault();
|
|
2132
|
+
let delta = -e.deltaY;
|
|
2133
|
+
if (e.deltaMode === 1) delta *= 40;
|
|
2134
|
+
if (e.deltaMode === 2) delta *= 800;
|
|
2135
|
+
camera.getWorldDirection(_wheelDir);
|
|
2136
|
+
const dist = camera.position.distanceTo(controls.target);
|
|
2137
|
+
const moveAmount = delta * 2e-3 * Math.max(dist * 0.1, 1);
|
|
2138
|
+
camera.position.addScaledVector(_wheelDir, moveAmount);
|
|
2139
|
+
controls.target.addScaledVector(_wheelDir, moveAmount);
|
|
2140
|
+
};
|
|
2141
|
+
canvas.addEventListener("wheel", onWheel, { passive: false });
|
|
2142
|
+
const scrollCleanup = () => canvas.removeEventListener("wheel", onWheel);
|
|
2130
2143
|
return {
|
|
2131
2144
|
scene,
|
|
2132
2145
|
camera,
|
|
@@ -2137,7 +2150,8 @@ function createScene(container, backgroundColor, style, rendererConfig) {
|
|
|
2137
2150
|
labels,
|
|
2138
2151
|
composer: null,
|
|
2139
2152
|
bloomPass: null,
|
|
2140
|
-
keyboard
|
|
2153
|
+
keyboard,
|
|
2154
|
+
scrollCleanup
|
|
2141
2155
|
};
|
|
2142
2156
|
}
|
|
2143
2157
|
function initBloom(state, nodeCount, style) {
|
|
@@ -2164,9 +2178,21 @@ function initBloom(state, nodeCount, style) {
|
|
|
2164
2178
|
}
|
|
2165
2179
|
function startAnimationLoop(state, onTick) {
|
|
2166
2180
|
let animFrame;
|
|
2181
|
+
let wasKeyboardActive = false;
|
|
2182
|
+
const _syncDir = new THREE__namespace.Vector3();
|
|
2167
2183
|
function animate() {
|
|
2168
2184
|
animFrame = requestAnimationFrame(animate);
|
|
2169
2185
|
const keyboardActive = state.keyboard.update();
|
|
2186
|
+
if (wasKeyboardActive && !keyboardActive) {
|
|
2187
|
+
const dist = state.camera.position.distanceTo(
|
|
2188
|
+
state.controls.target
|
|
2189
|
+
);
|
|
2190
|
+
state.camera.getWorldDirection(_syncDir);
|
|
2191
|
+
state.controls.target.copy(state.camera.position).add(_syncDir.multiplyScalar(dist));
|
|
2192
|
+
state.camera.up.set(0, 1, 0);
|
|
2193
|
+
state.camera.lookAt(state.controls.target);
|
|
2194
|
+
}
|
|
2195
|
+
wasKeyboardActive = keyboardActive;
|
|
2170
2196
|
if (!keyboardActive) state.controls.update();
|
|
2171
2197
|
if (state.selectionRing.visible) {
|
|
2172
2198
|
state.selectionRing.quaternion.copy(state.camera.quaternion);
|
|
@@ -2967,6 +2993,7 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
2967
2993
|
resizeObserver.disconnect();
|
|
2968
2994
|
interaction.cleanup();
|
|
2969
2995
|
state.keyboard.cleanup();
|
|
2996
|
+
state.scrollCleanup();
|
|
2970
2997
|
state.controls.dispose();
|
|
2971
2998
|
disposeObject(state.stars);
|
|
2972
2999
|
disposeObject(state.selectionRing);
|
|
@@ -3282,6 +3309,11 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3282
3309
|
}, 30);
|
|
3283
3310
|
return () => clearInterval(id);
|
|
3284
3311
|
}, [resolvedStyle.autoOrbit]);
|
|
3312
|
+
react.useEffect(() => {
|
|
3313
|
+
const s = sceneRef.current;
|
|
3314
|
+
if (!s) return;
|
|
3315
|
+
s.keyboard.setFlySpeed(resolvedStyle.flySpeed);
|
|
3316
|
+
}, [resolvedStyle.flySpeed]);
|
|
3285
3317
|
react.useImperativeHandle(ref, () => ({
|
|
3286
3318
|
cameraPosition(pos, lookAt, duration = 1e3) {
|
|
3287
3319
|
const s = sceneRef.current;
|
|
@@ -3359,6 +3391,16 @@ function NetworkGraph3DInner(props, ref) {
|
|
|
3359
3391
|
if (!s) return null;
|
|
3360
3392
|
s.renderer.render(s.scene, s.camera);
|
|
3361
3393
|
return s.renderer.domElement.toDataURL("image/png");
|
|
3394
|
+
},
|
|
3395
|
+
reheatLayout() {
|
|
3396
|
+
const gObj = graphObjRef.current;
|
|
3397
|
+
if (gObj == null ? void 0 : gObj.worker) {
|
|
3398
|
+
gObj.worker.postMessage({ type: "stop" });
|
|
3399
|
+
gObj.worker.terminate();
|
|
3400
|
+
gObj.worker = null;
|
|
3401
|
+
}
|
|
3402
|
+
dataRef.current.settled = false;
|
|
3403
|
+
setAppendedData((prev) => prev ? { ...prev } : { nodes: [], links: [] });
|
|
3362
3404
|
}
|
|
3363
3405
|
}));
|
|
3364
3406
|
return /* @__PURE__ */ jsxRuntime.jsx(
|