フローチャートや組織図など複雑なチャートを描くのは大変です。特に、インタラクティブな操作や編集が必要な場合は、専用のライブラリを使わないと実現が難しいでしょう。
今回はReactアプリの中で使えるReact Flowを試してみました。
Monacaアプリのベース
今回はFramework7 × Reactのテンプレートを使っています。
そして、追加でReact Flowを使うためのライブラリをインストールします。
コマンドラインで以下のように入力します。
次に、React Flowを使うためのセットアップです。ライブラリとCSSをインポートする必要があります。以下のようにインポートします。
あとは、ノードとエッジ(線)を定義して、React Flowコンポーネントに渡すだけです。
例えば、以下のようにノードとエッジを定義します。
これを React Flow コンポーネントに渡せば、あっという間にフローチャートが描画されます。

ここで、initialNodes
はフローチャートのノード(頂点)を表しています。各ノードには、一意のid
、画面上の位置を指定するposition
、そしてノードに表示するラベルを含むdata
オブジェクトを指定します。
一方、initialEdges
はノード間を結ぶエッジ(線)を表しています。各エッジには、一意のid
、エッジの始点となるノードのid
を指定するsource
、エッジの終点となるノードのid
を指定するtarget
を指定します。
以下のコードは、React FlowをReactアプリに組み込む例です。
このコードでは、まず必要なモジュールをインポートしています。ReactはReactライブラリ自体、PageはFramework7のページコンポーネント、ReactFlowはReact Flowライブラリ、そしてreactflow/dist/style.cssはReact Flowのスタイルシートです。
次に、initialNodesとinitialEdgesを定義しています。これらは、前の例と同じようにノードとエッジの初期設定です。
そして、HomePageコンポーネントを定義しています。このコンポーネントは、Framework7のPageコンポーネントを使用し、その中にdiv要素を配置しています。このdiv要素のスタイルは、幅と高さを100vw(ビューポート幅)と100vh(ビューポート高さ)に設定し、フローチャートが画面全体に表示されるようにしています。
div要素の中には、ReactFlowコンポーネントが配置されており、nodesとedgesのプロパティに、先ほど定義したinitialNodesとinitialEdgesを渡しています。これにより、定義したノードとエッジに基づいてフローチャートが描画されます。
最後に、HomePageコンポーネントをエクスポートしています。これにより、他のファイルからこのコンポーネントを使用できるようになります。
線をつなげる、ノードを動かす

React Flowでは、ノードを動かしたり、ノード同士を線で結んだりするために、useNodesState
と useEdgesState
という特別な関数を使います。これらの関数は、ノードと線の状態を管理してくれます。
以下のコードを見てみましょう。
まず、initialNodes
とinitialEdges
で、最初のノードと線を定義しています。これは前の例と同じですね。
次に、useNodesState
とuseEdgesState
を使って、ノードと線の状態を管理します。これらの関数は、現在のノードと線の状態(nodes
とedges
)、それらを更新するための関数(setNodes
とsetEdges
)、そしてノードや線が変更されたときに呼ばれるコールバック関数(onNodesChange
とonEdgesChange
)を返します。
onConnect関数は、新しい線が引かれたときに呼び出されます。この関数は、新しい線の情報をparamsとして受け取ります。
setEdges関数は、現在の線の状態を更新するための関数です。この関数は、現在の線の状態edsを受け取ります。
onConnect関数の中では、setEdges関数を使って、現在の線の状態edsに新しい線の情報paramsを追加しています。これは、addEdge関数を使って行われます。
最後に、ReactFlow
コンポーネントに、nodes
、edges
、onNodesChange
、onEdgesChange
、onConnect
を渡しています。これにより、React Flowは現在のノードと線の状態を知ることができ、ノードや線が変更されたときに適切に反応することができます。
このようにして、React Flowでノードを動かしたり、線で結んだりすることができるのです。少しコードが複雑に見えるかもしれませんが、基本的なアイデアは簡単です。ノードと線の状態を管理し、それらが変更されたときに適切に反応するだけなのです。
より複雑な例

ノードとエッジを追加すれば、より複雑なフローチャートを描くことができます。以下のコードを見てみましょう。
このコードでは、まずinitialNodes
とinitialEdges
で複数のノードとエッジを定義しています。各ノードはid
、sourcePosition
(エッジの出る位置)、targetPosition
(エッジの入る位置)、data
(ノードに表示するデータ)、position
(ノードの位置)などのプロパティを持っています。
エッジはid
、source
(始点のノードID)、target
(終点のノードID)、animated
(アニメーションの有無)などのプロパティを持っています。
HomePage
コンポーネントの中では、前の例と同様にuseNodesState
とuseEdgesState
を使ってノードとエッジの状態を管理しています。onConnect
関数も同様に定義されています。
ReactFlow
コンポーネントには、nodes
、edges
、onNodesChange
、onEdgesChange
、onConnect
に加えて、fitView
(全てのノードが画面内に収まるようにズームとパンを調整する)とattributionPosition
(帰属情報の位置)が指定されています。
このコードを実行すると、initialNodes
とinitialEdges
で定義されたノードとエッジを持つ、より複雑なフローチャートが表示されます。ユーザーはノードをドラッグしたり、ノード間に新しいエッジを引いたりすることができます。
このように、React Flowを使うと、複数のノードとエッジを定義することで、より複雑で対話的なフローチャートを簡単に作成することができるのです。
他の機能

React Flowには、他にもミニマップの表示や拡大・縮小などのコントロールを表示する機能があります。
fitViewプロパティを追加すると、フローチャートが画面内に収まるように自動的にサイズが調整されます。これは、フローチャートが画面からはみ出ることを防ぎ、常に全体が見えるようにしてくれます。
これらの機能を使うことで、フローチャートをより見やすく、操作しやすくすることができます。
まとめ
React Flowを使うと、複雑な表示のフローチャートをコードで簡単に描けます。さらにドラッグ&ドロップやノード同士の連結なども管理が容易です。編集結果をデータベースに保存すれば、ユーザーが自由にフローチャートを作成・共有できるアプリケーションも作れるでしょう。
ぜひReact Flowを使って、MonacaアプリのUIを充実させてみてください。