Graphページで使用しているSigma.jsには(実装時のメモ)、camera というモジュールがある。グラフ全体のどこをどう表示するか、の状態を管理する。

export interface Coordinates {
  x: number;
  y: number;
}

export interface CameraState extends Coordinates {
  angle: number;
  ratio: number;
}

camera の使い方はあまりドキュメントには書かれていないが、直接ソースコード camera.ts をみた方が早い。上のインターフェースはtypes.tsより。

camera.animate()

この camera には animate() というメソッドが実装されており、これを使えば特定のノードにズームインすることができる。

カメラ状態の取得と復元

まず、検索前のカメラ状態を保存・復元するメソッドを定義

renderer = new Sigma();
camera = renderer.getCamera();
const captureCameraState = () => {
  if (!camera) return null;
  const { x, y, angle, ratio } = camera.getState();
  return { x, y, angle, ratio };
};

const restoreCameraState = (state) => {
  if (!camera || !state) return;
  camera.animate(state, { duration: 350, easing: 'quadraticInOut' });
};

camera.getState() で現在の CameraState を取得し、camera.animate() でアニメーション付きで状態を復元する。

ノードへのフォーカス

特定ノードの座標を取得してカメラを移動するメソッドを定義

function focusOnNode(nodeId) {
  if (!camera || !renderer) return;
  try {
    const displayData = renderer.getNodeDisplayData(nodeId);
    const targetX = displayData.x;
    const targetY = displayData.y;
    if (typeof targetX !== 'number' || typeof targetY !== 'number') return;
    const currentState = camera.getState();
    const nextRatio = Math.max(0.08, currentState.ratio / 1.8);
    camera.animate(
      { ...currentState, x: targetX, y: targetY, ratio: nextRatio },
      { duration: 450, easing: 'quadraticInOut' }
    );
  } catch (error) {
    console.error('Failed to focus on search result node', error);
  }
}

ポイント

  1. renderer.getNodeDisplayData(nodeId) でレンダリング後の座標を取得
  2. camera.getState() で現在の状態を取得し、x, y を対象ノードの座標に、ratio を縮小(ズームイン)
  3. camera.animate() で滑らかに移動

1.の代わりあるいはフォールバックとして、nodeId を使って、グラフデータからgetNodeAttribute(nodeId, 'x')で xy座標を取得しても同じだと思う。

あとはこの focusOnNode() 関数を使えば、特定のノードにズームインでき、restoreCameraState() でズームアウトできる。

Graphページへ実装

早速Graphページに検索ボックスをつけて、検索して1つに絞られた場合、そのノードにズームインするようにしてみた。