[JavaScript] Mermaid / Graphviz / Cytoscape / elkjs 図式化/実用比較

はじめに

昨日、YoutubeのAI系チャンネルの一つ「AI整体師」さんが、まじん式プロンプトv3ついて絶賛されてて、AIと実装方法について雑談しながら拝見してました。

勉強を兼ねて近い物を作ってみようという話になり、手始めにJavascriptに関しては、図式化のスキルが抜けてるので情報をまとめてみました。

久しぶりのJavascript記事ですが、裏ではコードを書いてて、chromeのアドオン自作してたります。昨日、公式審査を通過して公開されました。

余談が長くなりましたが…

JavaScript には「テキスト → 図」に変換できるライブラリが複数あるようなので

  • Mermaid
  • Graphviz (viz.js)
  • Cytoscape.js
  • elkjs

の4つを取り上げ、最小コードと使いどころを比較します。

各ライブラリのクイックスタート

Mermaid - Markdownライクな記法

Markdownライクな記法で図を描けるので、READMEやブログ記事への埋め込みに最適。
以下はフローチャートの最小例。

■ Mermaidの主な特徴

  • テキストベースで図を作成:
    GUIに依存せず、コードを書く感覚でフローチャートやタイムラインなどの図を作成できます。 Markdown風のシンプルな記法:学習コストが低く、短いコードで複雑な図を表現できるため、手軽に利用できます。
  • 多様な図の種類に対応:
    フローチャート、シーケンス図、ガントチャート、クラス図など、様々な種類の図を描くことができます。
  • バージョン管理との親和性:
    コードベースで管理できるため、Gitなどのバージョン管理システムで図の変更履歴を追跡・管理できます。
  • 高い統合性:
    GitHub、GitLab、Visual Studio Codeなど、様々な開発ツールやプラットフォームでサポートされており、すぐに使い始められます。
  • ドキュメントとの一体化:
    プログラムのコードやドキュメントの中に直接図を埋め込むことができるため、情報の整理や視覚的な説明に役立ちます。
  • チームでの情報共有が容易:
    テキストで記述するため、チームメンバー間で図のコードを共有しやすく、誤解を減らし、スムーズなコミュニケーションに繋がります。

<script src="https://unpkg.com/mermaid@10/dist/mermaid.min.js"></script>
<div class="mermaid">
flowchart LR
  A[要件] --> B{設計OK?}
  B -- yes --> C[実装]
  B -- no  --> D[再検討]
</div>
<script>mermaid.initialize({ startOnLoad: true });</script>

■ 実行結果



DevToolsで見るとコードが消えたように見えますが、これは

<div class="mermaid">...</div>

内のテキストを、Mermaid のスクリプトがパースして SVGに変換 し 元のテキストに差し替え して為。

  • 「Mermaidは内部でHTMLを書き換えるので、ソース上から元の記述は消える」
  • 「実際にはSVGが生成されて描画されている」


Graphviz (viz.js) – レイアウト精度の高さ

DOT言語を使った定番。
DAG(有向非巡回グラフ)や依存関係を美しく描画できる。
Mermaidより細かい制御が効くのが特徴です。


■ 主な特徴

  • DOT言語による記述:
    グラフの構造(ノードやエッジなど)をDOT言語というテキストベースのシンプルな言語で記述します。
  • 自動レイアウト機能:
    ノードやエッジの配置を自動で決定してくれるため、手動で配置する手間が省けます。
  • 多様な画像形式への出力:
    PNG、JPEG、SVG、PDFなど、様々なフォーマットの画像ファイルを出力できます。
  • クロスプラットフォーム対応:
    Windows、Mac OS X、Linuxなど、様々なOSで利用可能です。

■ サンプル

<script src="https://unpkg.com/viz.js@2.1.2/viz.js"></script>
<script src="https://unpkg.com/viz.js@2.1.2/full.render.js"></script>
<div id="app"></div>
<script>
const dot = `digraph G {
  rankdir=LR;
  node [shape=box];
  A -> B -> C;
  B -> D;
}`;
new Viz().renderSVGElement(dot).then(el => document.getElementById('app').appendChild(el));
</script>

上記を読み込むと、左から右へ流れる依存関係図がSVGとして生成されます。

👉 ポイント

  • node [shape=box]; を入れると四角で揃う
    → 見栄えが良くなる
  • rankdir=TB; にすると上下方向に並べられる
  • subgraph cluster_x を使うとグルーピングできる
  • 出力は基本的にSVGなので、そのまま右クリック保存できる

■ 実行結果




Cytoscape.js – ネットワーク/相関図向け

Cytoscape.jsは、ウェブブラウザ上でグラフ理論に基づくネットワークの可視化と解析を行うためのJavaScriptライブラリです。

ノード(点)とエッジ(線)で構成されるグラフデータを、インタラクティブな操作を可能にする形で描写し、分析することができます。
MITライセンスで提供されており、商用利用も可。


■ 主な特徴

  • グラフ可視化と解析:
    ノードとエッジを持つデータ構造(グラフ)をウェブ上に表示し、分析するためのライブラリです。
  • インタラクティブな操作:
    ユーザーがマウス操作でグラフを拡大・縮小したり、ノードを移動させたりするなど、インタラクティブな操作が可能です。
  • カスタマイズ性:
    ノードやエッジのスタイル、レイアウトなど、表示方法を細かくカスタマイズできます。
  • MITライセンス:
    MITライセンスが採用されているため、商用・非商用を問わず、自由な利用と改変が可能です。
  • 汎用性:
    生物学的なネットワーク、ソーシャルネットワーク、コンピュータネットワークなど、グラフ構造を持つさまざまなデータを扱うことができます。

<div id="cy" style="width:600px;height:360px;border:1px solid #ccc"></div>
<script src="https://unpkg.com/cytoscape@3/dist/cytoscape.min.js"></script>
<script>
cytoscape({
  container: document.getElementById('cy'),
  elements: [
    { data: { id:'A' } },{ data:{ id:'B' } },{ data:{ id:'C' } },
    { data: { source:'A', target:'B' } },
    { data: { source:'B', target:'C' } }
  ],
  layout: { name:'breadthfirst', directed:true },
  style: [{ selector:'node', style:{ 'label':'data(id)' } }]
});
</script>

■ 操作性

  • ノードをドラッグしてレイアウトを変えられる
  • ホイール操作でズームイン/アウト可能

■ レイアウト切替

  • layout: { name:‘circle’ } や layout: { name:‘grid’ } など数種類ある

■ スタイル拡張

  • selector:’edge’, style:{ ’label’:‘data(weight)’ } みたいにエッジにもラベルを付けられる

■ 実行結果





elkjs – 軽量&自動整列に強い

ELK レイアウトアルゴリズムを JS から利用できる。
他のライブラリと違い 「座標を計算するだけ」 なので、その結果を自分で SVG や Canvas に描画する必要がある。


以下は最小サンプル。
3つのノード(要件→設計→実装)を定義し、エッジをつないでレイアウトを計算 → SVG に出力している。

<!doctype html><meta charset="utf-8">
<script src="https://unpkg.com/elkjs/lib/elk.bundled.js"></script>
<svg id="svg" width="640" height="240" style="border:1px solid #ccc"></svg>
<script>
const elk = new ELK();
const graph = {
  id:"root", layoutOptions:{ "elk.direction":"RIGHT" },
  children:[
    { id:"A", width:80, height:30, labels:[{text:"要件"}] },
    { id:"B", width:100, height:30, labels:[{text:"設計"}] },
    { id:"C", width:80, height:30, labels:[{text:"実装"}] }
  ],
  edges:[
    { id:"e1", sources:["A"], targets:["B"] },
    { id:"e2", sources:["B"], targets:["C"] }
  ]
};

elk.layout(graph).then(g => {
  const svg = document.getElementById("svg");
  // nodes
  g.children.forEach(n => {
    const r = document.createElementNS("http://www.w3.org/2000/svg","rect");
    r.setAttribute("x", n.x); r.setAttribute("y", n.y);
    r.setAttribute("width", n.width); r.setAttribute("height", n.height);
    r.setAttribute("fill","#fff"); r.setAttribute("stroke","#333");
    svg.appendChild(r);
    const t = document.createElementNS("http://www.w3.org/2000/svg","text");
    t.setAttribute("x", n.x + 8); t.setAttribute("y", n.y + 20);
    t.textContent = n.labels?.[0]?.text || n.id;
    svg.appendChild(t);
  });
  // edges
  g.edges.forEach(e => {
    const s = e.sections[0];
    const d = ["M",s.startPoint.x,s.startPoint.y,
               ...(s.bendPoints||[]).flatMap(b=>["L",b.x,b.y]),
               "L",s.endPoint.x,s.endPoint.y].join(" ");
    const path = document.createElementNS("http://www.w3.org/2000/svg","path");
    path.setAttribute("d", d); path.setAttribute("fill","none"); path.setAttribute("stroke","#888");
    svg.appendChild(path);
  });
});
</script>

👉 ポイント

  • id はノード・エッジともに必須
  • width / height を指定しないと配置できない
  • .then(console.log) とすれば座標だけ確認できる(描画しなくても良い)

■ 実行結果

比較と使い分け

  • 学習コスト

    • Mermaid:最小
    • Graphviz:中(DOT言語)
    • Cytoscape:中〜高(API設計理解が必要)
    • elkjs:中(設定オプション理解が必要)
  • レイアウト品質

    • Graphviz / elkjs が強い
    • Mermaid は簡易、Cytoscape は自由度が高い
  • インタラクティブ性

    • Cytoscape.js が唯一の本格対応
  • ワークフローとの相性

    • Markdown / Hugo記事内なら Mermaid が楽
    • 大規模可視化や解析は Cytoscape
    • DAGや依存関係は Graphviz / elkjs


① 導入の実務

  • Mermaid:<script src="https://unpkg.com/mermaid@10/dist/mermaid.min.js"></script>
  • Graphviz(viz.js):viz.jsfull.render.js の2本を読み込む(WASM実行に必要)
  • Cytoscape:<script src="https://unpkg.com/cytoscape@3/dist/cytoscape.min.js"></script>
  • elkjs:<script src="https://unpkg.com/elkjs/lib/elk.bundled.js"></script>


② よくあるハマりどころ

  • Mermaid:描画後は <div class="mermaid"> の中身が SVGに差し替えられる(DevToolsで元のテキストは消えたように見える)
  • Graphviz:rankdir=LR|TBsubgraph cluster_*向きとグループnode [shape=box]見栄え統一
  • Cytoscape:コンテナ要素の幅・高さ必須layoutbreadthfirst/circle/grid/preset を切替
  • elkjs:ノード/エッジすべてに id 必須、ノードは width/height 必須、座標だけ返すので描画は自分で行う


③ SVGをその場で保存

<button id="save">SVGを保存</button>
<script>
document.getElementById('save').onclick = () => {
  const svg = document.querySelector('svg'); // ページ内で最初のSVGを保存
  const blob = new Blob([new XMLSerializer().serializeToString(svg)], {type:'image/svg+xml'});
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob); a.download = 'diagram.svg'; a.click();
  URL.revokeObjectURL(a.href);
};
</script>

まとめ

  • まずは Mermaid を導入すると学びやすい
  • 複雑化したら Graphviz / elkjs に進む
  • 相関関係やネットワーク探索は Cytoscape.js

図式化ライブラリはそれぞれに得意分野があり、「文章で伝えるより、図で直感的に見せる」ための大きな武器になります。

次回の記事では、

GAS や AI と組み合わせた自動化ワークフロー

  • ChatGPT で生成したテキストを自動で図式化
  • GAS で定期的に図を更新/スライド化
  • Hugo ブログにワンクリックで埋め込む

といった流れを予定してます。

関連リンク