ReactFlowでnodeの移動範囲を可視化する方法

# はじめに
ReactFlowでnodeの移動範囲を可視化する方法を調べたのですが、あまり出てこなかったので、まとめました。

以下は、ChatGPTに出してもらった、ReactFlowの基本コードです。
``` App.js
import React, { useCallback, useState } from "react";
import ReactFlow, {
  Background,
  Controls,
  MiniMap,
  useNodesState,
  useEdgesState,
} from "reactflow";
import "reactflow/dist/style.css";
import "./App.css";

const initialNodes = [
  {
    id: "1",
    type: "default",
    position: { x: 250, y: 150 },
    data: { label: "Hello, React Flow!" },
  },
];

const initialEdges = [];

const App = () => {
  // ノードとエッジの状態を管理
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
      >
        <Background />
        <Controls />
        <MiniMap />
      </ReactFlow>
    </div>
  );
};

export default App;

```

# 方法
## 視界とノードの移動範囲を設定する
このままでは、視界もノードも、自由にどこへでも移動できるので、動かせる範囲を設定します。
以下の公式ドキュメントに書かれている、translateExtentとnodeExtentを使用します。
公式Doc: https://reactflow.dev/api-reference/react-flow

以下、サンプルコード。
```App.js
import React from "react";
import ReactFlow, {
  Background,
  Controls,
  MiniMap,
  useNodesState,
  useEdgesState,
} from "reactflow";
import "reactflow/dist/style.css";
import "./App.css";

const initialNodes = [
  {
    id: "1",
    type: "default",
    position: { x: 250, y: 150 },
    data: { label: "Hello, React Flow!" },
  },
];

const initialEdges = [];

const nodeExtent = [
  [0, 0], // 最小範囲 (左上の座標)
  [500, 300], // 最大範囲 (右下の座標)
];

const translateExtent = [
  [0, 0], // 最小視界 (左上の座標)
  [600, 400], // 最大視界 (右下の座標)
];

const App = () => {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        nodeExtent={nodeExtent} // ノードの移動範囲を制限
        translateExtent={translateExtent} // カメラの移動範囲を制限
      >
        <Background />
        <Controls />
        <MiniMap />
      </ReactFlow>
    </div>
  );
};

export default App;

```

これで動かせる範囲を調整できるようになります。



## ノード移動範囲を可視化する
ここまでは調べて出るのですが、このノードが動かせる範囲を可視化しようとすると、なぜか方法があまり出ませんでした。

少し強引ですが、以下のような方法が使えます。

**① css で react-flow__container クラスに対して、border、またはoutlineを設定する**
　以下の画像の通り、ReactFlowには react-flow__container などのクラスがあるので、
 　そのクラスに対し、css でボーダーを付けてしまう。
![スクリーンショット 2025-02-16 150354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3831969/2a2c90d4-2441-4caa-827d-afe3d99d6e01.png)
```App.css
.react-flow__container{
  border: 1px dashed #222;
}
```
:::note warn
追記：今回のサンプルコードではborderを使用しているが、borderは要素の大きさに影響が出るので、outlineの方が望ましい。
:::


**② css で react-flow__container クラスにwidthとheightを設定し、nodeExtextと合わせる**
　同様の形で react-flow__container にwidthとheightを設定する。
　今回の場合は、nodeExtentの横が500、縦が300となっているので、widthは500px、heightは300pxとなる。
　（同じ値にしてもずれることがあるので、そこは要調整。）
```App.js
const nodeExtent = [
  [0, 0], // 最小範囲 (左上の座標)
  [500, 300], // 最大範囲 (右下の座標)
];
```
```App.css
.react-flow__container{
  width: 500px;
  height: 300px;
  border: 1px dashed #222;
}
```


# まとめ
最終的なコードは以下。
```App.js
import React from "react";
import ReactFlow, {
  Background,
  Controls,
  MiniMap,
  useNodesState,
  useEdgesState,
} from "reactflow";
import "reactflow/dist/style.css";
import "./App.css";

const initialNodes = [
  {
    id: "1",
    type: "default",
    position: { x: 250, y: 150 },
    data: { label: "Hello, React Flow!" },
  },
];

const initialEdges = [];

const nodeExtent = [
  [0, 0], // 最小範囲 (左上の座標)
  [500, 300], // 最大範囲 (右下の座標)
];

const translateExtent = [
  [0, 0], // 最小視界 (左上の座標)
  [600, 400], // 最大視界 (右下の座標)
];

const App = () => {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

  return (
    <div style={{ width: "100vw", height: "100vh" }}>
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        nodeExtent={nodeExtent} // ノードの移動範囲を制限
        translateExtent={translateExtent} // カメラの移動範囲を制限
      >
        <Background />
        <Controls />
        <MiniMap />
      </ReactFlow>
    </div>
  );
};

export default App;

```
```App.css
/* 以下の内容を追記 */
.react-flow__container{
  width: 500px;
  height: 300px;
  border: 1px dashed #222;
}
```
完成したフローのスクショ
![スクリーンショット 2025-02-16 151405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3831969/19a01e59-1020-444b-9273-03827425aa92.png)


こういった方法で視界（カメラ）と、ノードの範囲を設定・可視化することができます。

以上です。