@cocorof/graphier 1.2.0 → 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 CHANGED
@@ -52,8 +52,8 @@ function hexToRgb(hex) {
52
52
  return [(n >> 16) / 255, (n >> 8 & 255) / 255, (n & 255) / 255];
53
53
  }
54
54
  function rgbToHex(r, g, b) {
55
- const clamp2 = (v) => Math.round(Math.max(0, Math.min(1, v)) * 255);
56
- const hex = clamp2(r) << 16 | clamp2(g) << 8 | clamp2(b);
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);
57
57
  return "#" + hex.toString(16).padStart(6, "0");
58
58
  }
59
59
  function brighten(hex, factor) {
@@ -1972,61 +1972,45 @@ function disposeLabelSystem(state) {
1972
1972
  }
1973
1973
  state.textureCache.clear();
1974
1974
  }
1975
- const ORBIT_ACCEL = 12e-4;
1976
- const ORBIT_MAX_SPEED = 0.06;
1977
- const ORBIT_DAMPING = 0.88;
1975
+ const ORBIT_ROTATE_SPEED = 0.02;
1978
1976
  const ORBIT_ZOOM_FACTOR = 0.015;
1979
- const ORBIT_DEAD_ZONE = 1e-4;
1980
- const FLY_ACCEL = 6e-3;
1981
- const FLY_FRICTION = 0.92;
1982
- const FLY_MAX_THRUST = 0.18;
1977
+ const FLY_THRUST_SPEED = 0.08;
1983
1978
  const FLY_TURN_RATE = 8e-3;
1984
- const FLY_DEAD_ZONE = 2e-4;
1985
1979
  const _offset = new THREE__namespace.Vector3();
1986
1980
  const _right = new THREE__namespace.Vector3();
1987
1981
  const _q = new THREE__namespace.Quaternion();
1988
1982
  const _dir = new THREE__namespace.Vector3();
1989
1983
  const _worldUp = new THREE__namespace.Vector3(0, 1, 0);
1990
- function clamp(v, min, max) {
1991
- return v < min ? min : v > max ? max : v;
1992
- }
1993
1984
  function createOrbitUpdate(camera, controls, keys) {
1994
- const vel = { zoom: 0, azimuth: 0, polar: 0 };
1995
1985
  return function update() {
1996
- if (keys["z"] || keys["Z"]) vel.zoom -= ORBIT_ACCEL;
1997
- if (keys["x"] || keys["X"]) vel.zoom += ORBIT_ACCEL;
1998
- if (keys["ArrowLeft"]) vel.azimuth -= ORBIT_ACCEL;
1999
- if (keys["ArrowRight"]) vel.azimuth += ORBIT_ACCEL;
2000
- if (keys["ArrowUp"]) vel.polar -= ORBIT_ACCEL;
2001
- if (keys["ArrowDown"]) vel.polar += ORBIT_ACCEL;
2002
- vel.zoom = clamp(vel.zoom, -ORBIT_MAX_SPEED, ORBIT_MAX_SPEED);
2003
- vel.azimuth = clamp(vel.azimuth, -ORBIT_MAX_SPEED, ORBIT_MAX_SPEED);
2004
- vel.polar = clamp(vel.polar, -ORBIT_MAX_SPEED, ORBIT_MAX_SPEED);
2005
- vel.zoom *= ORBIT_DAMPING;
2006
- vel.azimuth *= ORBIT_DAMPING;
2007
- vel.polar *= ORBIT_DAMPING;
2008
- if (Math.abs(vel.zoom) < ORBIT_DEAD_ZONE) vel.zoom = 0;
2009
- if (Math.abs(vel.azimuth) < ORBIT_DEAD_ZONE) vel.azimuth = 0;
2010
- if (Math.abs(vel.polar) < ORBIT_DEAD_ZONE) vel.polar = 0;
2011
- 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;
2012
1996
  if (!hasMotion) return false;
2013
1997
  const target = controls.target;
2014
1998
  _offset.copy(camera.position).sub(target);
2015
1999
  let radius = _offset.length();
2016
- if (vel.zoom !== 0) {
2017
- radius *= 1 + vel.zoom * ORBIT_ZOOM_FACTOR * radius * 0.01;
2000
+ if (zoom !== 0) {
2001
+ radius *= 1 + zoom * ORBIT_ZOOM_FACTOR * radius * 0.01;
2018
2002
  radius = Math.max(controls.minDistance, Math.min(controls.maxDistance, radius));
2019
2003
  }
2020
- if (vel.azimuth !== 0) {
2021
- _q.setFromAxisAngle(camera.up, -vel.azimuth);
2004
+ if (azimuth !== 0) {
2005
+ _q.setFromAxisAngle(camera.up, -azimuth);
2022
2006
  _offset.applyQuaternion(_q);
2023
2007
  }
2024
- if (vel.polar !== 0) {
2008
+ if (polar !== 0) {
2025
2009
  _right.copy(_offset).normalize().cross(camera.up).normalize();
2026
2010
  if (_right.lengthSq() < 1e-3) {
2027
2011
  _right.setFromMatrixColumn(camera.matrixWorld, 0);
2028
2012
  }
2029
- _q.setFromAxisAngle(_right, vel.polar);
2013
+ _q.setFromAxisAngle(_right, polar);
2030
2014
  _offset.applyQuaternion(_q);
2031
2015
  camera.up.applyQuaternion(_q).normalize();
2032
2016
  }
@@ -2038,44 +2022,37 @@ function createOrbitUpdate(camera, controls, keys) {
2038
2022
  };
2039
2023
  }
2040
2024
  function createFlyUpdate(camera, controls, keys, state) {
2041
- const vel = { thrust: 0, yaw: 0, pitch: 0 };
2042
2025
  return function update() {
2043
2026
  const speedMul = state.flySpeed;
2044
- if (keys["z"] || keys["Z"]) vel.thrust += FLY_ACCEL * speedMul;
2045
- if (keys["x"] || keys["X"]) vel.thrust -= FLY_ACCEL * speedMul;
2046
- if (keys["a"] || keys["A"] || keys["ArrowLeft"]) vel.yaw += FLY_TURN_RATE;
2047
- if (keys["d"] || keys["D"] || keys["ArrowRight"]) vel.yaw -= FLY_TURN_RATE;
2048
- if (keys["w"] || keys["W"] || keys["ArrowUp"]) vel.pitch += FLY_TURN_RATE;
2049
- if (keys["s"] || keys["S"] || keys["ArrowDown"]) vel.pitch -= FLY_TURN_RATE;
2050
- const lookDist = camera.position.distanceTo(controls.target);
2051
- const distScale = Math.max(0.3, lookDist * 3e-3);
2052
- vel.thrust = clamp(vel.thrust, -FLY_MAX_THRUST * distScale * speedMul, FLY_MAX_THRUST * distScale * speedMul);
2053
- vel.yaw = clamp(vel.yaw, -FLY_TURN_RATE * 2, FLY_TURN_RATE * 2);
2054
- vel.pitch = clamp(vel.pitch, -FLY_TURN_RATE * 2, FLY_TURN_RATE * 2);
2055
- vel.thrust *= FLY_FRICTION;
2056
- vel.yaw *= FLY_FRICTION;
2057
- vel.pitch *= FLY_FRICTION;
2058
- if (Math.abs(vel.thrust) < FLY_DEAD_ZONE) vel.thrust = 0;
2059
- if (Math.abs(vel.yaw) < FLY_DEAD_ZONE) vel.yaw = 0;
2060
- if (Math.abs(vel.pitch) < FLY_DEAD_ZONE) vel.pitch = 0;
2061
- const hasMotion = vel.thrust !== 0 || vel.yaw !== 0 || vel.pitch !== 0;
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;
2062
2037
  if (!hasMotion) return false;
2063
- if (vel.yaw !== 0) {
2038
+ if (yaw !== 0) {
2064
2039
  const upDot = camera.up.dot(_worldUp);
2065
2040
  const yawSign = upDot < 0 ? -1 : 1;
2066
- _q.setFromAxisAngle(_worldUp, vel.yaw * yawSign);
2041
+ _q.setFromAxisAngle(_worldUp, yaw * yawSign);
2067
2042
  camera.quaternion.premultiply(_q);
2068
2043
  camera.up.applyQuaternion(_q).normalize();
2069
2044
  }
2070
- if (vel.pitch !== 0) {
2045
+ if (pitch !== 0) {
2071
2046
  _right.setFromMatrixColumn(camera.matrixWorld, 0).normalize();
2072
- _q.setFromAxisAngle(_right, vel.pitch);
2047
+ _q.setFromAxisAngle(_right, pitch);
2073
2048
  camera.quaternion.premultiply(_q);
2074
2049
  camera.up.applyQuaternion(_q).normalize();
2075
2050
  }
2076
- if (vel.thrust !== 0) {
2051
+ if (thrust !== 0) {
2052
+ const lookDist = camera.position.distanceTo(controls.target);
2053
+ const distScale = Math.max(0.3, lookDist * 3e-3);
2077
2054
  camera.getWorldDirection(_dir);
2078
- _dir.multiplyScalar(vel.thrust * distScale * 100);
2055
+ _dir.multiplyScalar(thrust * distScale * 100);
2079
2056
  camera.position.add(_dir);
2080
2057
  controls.target.add(_dir);
2081
2058
  }
@@ -2148,6 +2125,21 @@ function createScene(container, backgroundColor, style, rendererConfig) {
2148
2125
  scene.add(labels.group);
2149
2126
  const cameraMode = (rendererConfig == null ? void 0 : rendererConfig.cameraMode) ?? "fly";
2150
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);
2151
2143
  return {
2152
2144
  scene,
2153
2145
  camera,
@@ -2158,7 +2150,8 @@ function createScene(container, backgroundColor, style, rendererConfig) {
2158
2150
  labels,
2159
2151
  composer: null,
2160
2152
  bloomPass: null,
2161
- keyboard
2153
+ keyboard,
2154
+ scrollCleanup
2162
2155
  };
2163
2156
  }
2164
2157
  function initBloom(state, nodeCount, style) {
@@ -2185,9 +2178,21 @@ function initBloom(state, nodeCount, style) {
2185
2178
  }
2186
2179
  function startAnimationLoop(state, onTick) {
2187
2180
  let animFrame;
2181
+ let wasKeyboardActive = false;
2182
+ const _syncDir = new THREE__namespace.Vector3();
2188
2183
  function animate() {
2189
2184
  animFrame = requestAnimationFrame(animate);
2190
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;
2191
2196
  if (!keyboardActive) state.controls.update();
2192
2197
  if (state.selectionRing.visible) {
2193
2198
  state.selectionRing.quaternion.copy(state.camera.quaternion);
@@ -2988,6 +2993,7 @@ function NetworkGraph3DInner(props, ref) {
2988
2993
  resizeObserver.disconnect();
2989
2994
  interaction.cleanup();
2990
2995
  state.keyboard.cleanup();
2996
+ state.scrollCleanup();
2991
2997
  state.controls.dispose();
2992
2998
  disposeObject(state.stars);
2993
2999
  disposeObject(state.selectionRing);