2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JointJSAdvent Calendar 2023

Day 20

【JointJS】DirectedGraphを利用してツリー形式の図を作成する

Last updated at Posted at 2023-12-19

JointJSにはDirectedGraphという、有向グラフを作成するためのレイアウト機能が用意されています。今回はそちらを使ってツリー形式の図を作成していきます。

完成イメージ

以下のようなツリー形式の図を作成できます。
各四角形の座標は四角形に紐づいたLinkの情報からDirectedGraphが自動計算して決定してくれます

image.png

実装

下準備

DirectedGraphを使用するためには、dagregraphlibというライブラリを追加で取り込む必要があります。お手軽に利用する場合は以下の<script>タグを記載すればOKです。

<script src="https://dagrejs.github.io/project/graphlib/latest/graphlib.min.js"></script>
<script src="https://dagrejs.github.io/project/dagre/latest/dagre.min.js"></script>

その他、npmでダウンロードする方法等もあります。詳細については各ライブラリのWikiを参照してください。

手順1. 並べるElementをインスタンス化

並べる対象のElementをインスタンス化し、Graphに追加します。

joint.shapes.standard.Rectangle.define('example.MyRect', {
  // 中略
});

const rect1 = joint.shapes.example.MyRect.create('1');
const rect2 = joint.shapes.example.MyRect.create('2');
const rect3 = joint.shapes.example.MyRect.create('3');
const rect4 = joint.shapes.example.MyRect.create('4');
const rect5 = joint.shapes.example.MyRect.create('5');
const rect6 = joint.shapes.example.MyRect.create('6');
const rect7 = joint.shapes.example.MyRect.create('7');
const rect8 = joint.shapes.example.MyRect.create('8');
const rect9 = joint.shapes.example.MyRect.create('9');

const rectangles = [rect1, rect2, rect3, rect4, rect5, rect6, rect7, rect8, rect9];
graph.addCells(rectangles);

手順2. 並べるElementをLinkでつなぐ

Linkをインスタンス化し、sourcetargetにつなぎたいElementを設定します。

const link1_2 = new joint.shapes.standard.Link({source: rect1, target: rect2});
const link1_3 = new joint.shapes.standard.Link({source: rect1, target: rect3});
const link2_4 = new joint.shapes.standard.Link({source: rect2, target: rect4});
const link2_5 = new joint.shapes.standard.Link({source: rect2, target: rect5});
const link3_6 = new joint.shapes.standard.Link({source: rect3, target: rect6});
const link4_7 = new joint.shapes.standard.Link({source: rect4, target: rect7});
const link4_8 = new joint.shapes.standard.Link({source: rect4, target: rect8});
const link5_9 = new joint.shapes.standard.Link({source: rect5, target: rect9});

const links = [link1_2, link1_3, link2_4, link2_5, link3_6, link4_7, link4_8, link5_9]; 
graph.addCells(links);

手順3. layoutメソッドを呼び出す

DirectedGraphのlayoutメソッドを呼び出して整列を実行します。

joint.layout.DirectedGraph.layout(graph, {
    nodeSep: 50,
    edgeSep: 80,
    rankDir: "TB"
});

第2引数に指定するオブジェクトには以下のような値を指定できます。

nodeSep

並列に存在しているElement間の距離を指定します。

image.png

rankSep

親子関係にあるElement間の距離を指定します。

image.png

marginX / marginY

生成されるDirectedGraphの外側に設けるマージンの長さを指定します。

rankDir

Elementを整列する方向をしていします。

TB(top-bottom)を指定した場合

image.png

LR(left-right)を指定した場合

image.png

ranker

階層構造を整列する際のアルゴリズムを指定します。
階層数が異なる枝があるときに、長い方に合わせて位置を決定するのか、短い方に合わせて位置を決定するのか、などのアルゴリズムが切り替えられるようになります。

ranker=network-simplexのときの実行結果

image.png

ranker=longest-pathのときの実行結果

image.png

network-simplexの結果と比べると3,6の位置がズレています。

DirectedGraphを使うメリット・デメリット

私なりに考えるDirectedGraphのメリット・デメリットは以下となります。

メリット

  • 座標の計算を行わずにお手軽にElementを整列できる
  • 線の種類や向きはある程度は指定可能
  • Elementが増えた場合にも対応できる

デメリット1

  • 細かい線の位置指定はできない
  • オプション以上のカスタマイズができない

まとめ

今回は有向グラフを作成できるDirectedGraphの機能を紹介しました。お手軽にツリー構造の図を作成できるため、簡単な要件であれば有用性の高い機能です。ツリー構造を作成する際は利用を検討してみてください。

※この記事は JointJS Advent Calendar 2023 の記事です。他の記事を読む場合はカレンダーのページを参照してください。

  1. 私の開発プロジェクトではデメリットのカスタマイズ性の乏しさが仇となり、DirectedGraphの使用を見送りにしました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?