graphviz ちっくなので飛び付く、のうち一つ。
jQuery: Cytoscape.js お試せた
前置き(1)
一つ前の投稿でこんなこと書いた:
その「その他」をいくつか試してみたいと思っていて、今一番興味があるのが、graphviz と同じノリの Cytoscape.js なんだけれど、これは一つには「本格的に遊びたい」、もう一つには「ドキュメントの出来がかなりよろしくない」の2つの理由から、ちょっとだけ後回し気分になってる。
これに少し補足しておくと、既に目星をつけているものの中で「graphviz っぽい」のは Cytoscape.js のほかに Sigma.js も多分そうなんじゃないかと思っている。
前置き(2)
「graphviz ちっく」とワタシが言っているニュアンスは実は「機能が似てる」ということ以上のことを含んでいる。これをちょっとだけ説明しとく。graphviz を少しも知らない人はあまりこの感覚がわからないと思うから。
基本的に graphviz やこれに似たものがターゲットとするのは、「手描き出来ないような複雑なグラフ」である。より具体的には、Graph theory (グラフ理論)が扱うようなものたちである。Gallery を見てもらうのがいい。
もちろんワタシが今考えてるようなニーズ、つまり「ちょっとお手軽にも少し単純なもの」を描くのにも使えるけれど、それを本来のユースケースだと理解すると、大抵の場合はストレスばっかりたまって仕方ないはず。すなわち「大量のノードを扱う」ことに主眼が置かれているので、大抵「言うことを聞いてくれない」のだ。無論可能な限り自動で賢くやろうとするから。なので、カチっとしてキッチリとしたあなたによる完全制御可能なグラフ、を目指しちゃダメ。そんなこと出来ない。多少のおかしな配置くらいは目をつぶれるような目的に使うこと。
そしてそういう相手に使うものなので、ということは、graphviz であれば DOT 言語を、Cytoscape.js であれば javascript を「手書きする」のは普通はかなり無理がある、ということ。ほとんどの場合は他の何か(ワタシなら Python など)の助けを借りて生成することになるし、そうしないで「なんだよ使いににくい」と思うなら、やはり使うべき相手を間違っているか、もしくは Cytoscape.js や graphviz を選んでいることのどちらかが間違いである。
てわけで、はじめの一歩
さて。「とりあえず手始めたい」と思ったはいいが、「ドキュメントの出来がかなりよろしくない」はやってみたら想像以上だった。わかってしまえば大した話ではないが、「手始める」のは結構ややこしい。
とりあえず出来た一つはこれ:
「フレームのソースを表示」してくれ、と言いたかったが、右クリックが使えないようなので:
1 <html>
2 <head jang="ja">
3 <meta charset="UTF-8">
4 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
5 <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.7/cytoscape.min.js"></script>
6
7 <!-- for 'layout: "dagre"' -->
8 <script src="https://cdn.rawgit.com/cpettitt/dagre/v0.7.4/dist/dagre.min.js"></script>
9 <script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
10 <style>
11 #cy {
12 width: 100%; /* MUST */
13 height: 100%; /* MUST */
14
15 /**
16 position: absolute;
17 left: 0;
18 top: 0;
19 z-index: 999;
20 */
21 }
22 </style>
23 </head>
24 <body>
25 <div id="cy"></div>
26 <script>
27 var cy = window.cy = cytoscape({
28 container: document.getElementById('cy'),
29
30 boxSelectionEnabled: false,
31 autounselectify: true,
32
33 layout: {
34 name: 'dagre'
35 },
36 style: [
37 {
38 selector: 'node',
39 style: {
40 'content': 'data(id)', /* must be specified if you want to display the node text */
41 /**
42 'text-opacity': 0.5,
43 'text-valign': 'center',
44 'text-halign': 'right',
45 */
46 'background-color': '#11479e'
47 }
48 },
49 {
50 selector: 'edge',
51 style: {
52 'target-arrow-shape': 'triangle',
53 'curve-style': 'bezier',
54 'target-arrow-color': '#9dbaea',
55 'width': 4,
56 'line-color': '#9dbaea',
57 }
58 }
59 ],
60
61 elements: {
62 "nodes": [
63 { "data": { "id": "5th Edition" } },
64 { "data": { "id": "6th Edition" } },
65 { "data": { "id": "PWB 1.0" } },
66 { "data": { "id": "LSX" } },
67 { "data": { "id": "1 BSD" } },
68 { "data": { "id": "Mini Unix" } },
69 { "data": { "id": "Wollongong" } },
70 { "data": { "id": "Interdata" } },
71 { "data": { "id": "Unix/TS 3.0" } },
72 { "data": { "id": "PWB 2.0" } },
73 { "data": { "id": "7th Edition" } },
74 { "data": { "id": "8th Edition" } },
75 { "data": { "id": "32V" } },
76 { "data": { "id": "V7M" } },
77 { "data": { "id": "Ultrix-11" } },
78 { "data": { "id": "Xenix" } },
79 { "data": { "id": "UniPlus+" } },
80 { "data": { "id": "9th Edition" } },
81 { "data": { "id": "2 BSD" } },
82 { "data": { "id": "2.8 BSD" } },
83 { "data": { "id": "2.9 BSD" } },
84 { "data": { "id": "3 BSD" } },
85 { "data": { "id": "4 BSD" } },
86 { "data": { "id": "4.1 BSD" } },
87 { "data": { "id": "4.2 BSD" } },
88 { "data": { "id": "4.3 BSD" } },
89 { "data": { "id": "Ultrix-32" } },
90 { "data": { "id": "PWB 1.2" } },
91 { "data": { "id": "USG 1.0" } },
92 { "data": { "id": "CB Unix 1" } },
93 { "data": { "id": "USG 2.0" } },
94 { "data": { "id": "CB Unix 2" } },
95 { "data": { "id": "CB Unix 3" } },
96 { "data": { "id": "Unix/TS++" } },
97 { "data": { "id": "PDP-11 Sys V" } },
98 { "data": { "id": "USG 3.0" } },
99 { "data": { "id": "Unix/TS 1.0" } },
100 { "data": { "id": "TS 4.0" } },
101 { "data": { "id": "System V.0" } },
102 { "data": { "id": "System V.2" } },
103 { "data": { "id": "System V.3" } }
104 ],
105 "edges": [
106 { "data": { "source": "5th Edition", "target": "6th Edition" } },
107 { "data": { "source": "5th Edition", "target": "PWB 1.0" } },
108 { "data": { "source": "6th Edition", "target": "LSX" } },
109 { "data": { "source": "6th Edition", "target": "1 BSD" } },
110 { "data": { "source": "6th Edition", "target": "Mini Unix" } },
111 { "data": { "source": "6th Edition", "target": "Wollongong" } },
112 { "data": { "source": "6th Edition", "target": "Interdata" } },
113 { "data": { "source": "Interdata", "target": "Unix/TS 3.0" } },
114 { "data": { "source": "Interdata", "target": "PWB 2.0" } },
115 { "data": { "source": "Interdata", "target": "7th Edition" } },
116 { "data": { "source": "7th Edition", "target": "8th Edition" } },
117 { "data": { "source": "7th Edition", "target": "32V" } },
118 { "data": { "source": "7th Edition", "target": "V7M" } },
119 { "data": { "source": "7th Edition", "target": "Ultrix-11" } },
120 { "data": { "source": "7th Edition", "target": "Xenix" } },
121 { "data": { "source": "7th Edition", "target": "UniPlus+" } },
122 { "data": { "source": "V7M", "target": "Ultrix-11" } },
123 { "data": { "source": "8th Edition", "target": "9th Edition" } },
124 { "data": { "source": "1 BSD", "target": "2 BSD" } },
125 { "data": { "source": "2 BSD", "target": "2.8 BSD" } },
126 { "data": { "source": "2.8 BSD", "target": "Ultrix-11" } },
127 { "data": { "source": "2.8 BSD", "target": "2.9 BSD" } },
128 { "data": { "source": "32V", "target": "3 BSD" } },
129 { "data": { "source": "3 BSD", "target": "4 BSD" } },
130 { "data": { "source": "4 BSD", "target": "4.1 BSD" } },
131 { "data": { "source": "4.1 BSD", "target": "4.2 BSD" } },
132 { "data": { "source": "4.1 BSD", "target": "2.8 BSD" } },
133 { "data": { "source": "4.1 BSD", "target": "8th Edition" } },
134 { "data": { "source": "4.2 BSD", "target": "4.3 BSD" } },
135 { "data": { "source": "4.2 BSD", "target": "Ultrix-32" } },
136 { "data": { "source": "PWB 1.0", "target": "PWB 1.2" } },
137 { "data": { "source": "PWB 1.0", "target": "USG 1.0" } },
138 { "data": { "source": "PWB 1.2", "target": "PWB 2.0" } },
139 { "data": { "source": "USG 1.0", "target": "CB Unix 1" } },
140 { "data": { "source": "USG 1.0", "target": "USG 2.0" } },
141 { "data": { "source": "CB Unix 1", "target": "CB Unix 2" } },
142 { "data": { "source": "CB Unix 2", "target": "CB Unix 3" } },
143 { "data": { "source": "CB Unix 3", "target": "Unix/TS++" } },
144 { "data": { "source": "CB Unix 3", "target": "PDP-11 Sys V" } },
145 { "data": { "source": "USG 2.0", "target": "USG 3.0" } },
146 { "data": { "source": "USG 3.0", "target": "Unix/TS 3.0" } },
147 { "data": { "source": "PWB 2.0", "target": "Unix/TS 3.0" } },
148 { "data": { "source": "Unix/TS 1.0", "target": "Unix/TS 3.0" } },
149 { "data": { "source": "Unix/TS 3.0", "target": "TS 4.0" } },
150 { "data": { "source": "Unix/TS++", "target": "TS 4.0" } },
151 { "data": { "source": "CB Unix 3", "target": "TS 4.0" } },
152 { "data": { "source": "TS 4.0", "target": "System V.0" } },
153 { "data": { "source": "System V.0", "target": "System V.2" } },
154 { "data": { "source": "System V.2", "target": "System V.3" } }
155 ]
156 },
157
158 });
159 </script>
160 </body>
161 </html>
elements の部分は graphviz がわかる人ならお馴染み(だけれど DOT よりダルい)とわかるだろう。
「手始める」にあたって個人的にうわぁと思ったポイントは以下:
- layout の種類ごとに追加ライブラリが必要 (今回の例の場合は
dagre.js
、cytoscape-dagre.js
) - スタイルなし、から始められない。不可欠なものがいくつかある。
- つまり「ださくてもいいからミニマルから始めたい」という学習スタイルの人にキツい。
- コンテナ(今回の例では
cy
)のwidth
,height
がないとダメ。 cytoscape
に渡しているコンフィギュレーションに指定してるstyle
も、全くなしで始めると意味わからんものになるので、へろわるどでも付けて手始めた方がよろしい。
まぁこうやって誰か人柱がいれば、後追いの人はなんてことはないと思うんだろうけどね。
さて、「ドキュメントがヒドい」だけどね、上の「出来てみた」に辿りついた手順はこんななのよ:
- Demos からやりたいのに近いものの下にくっついてる GitHub へ Go! ボタン。
- そのデモの html を読んで、必要なライブラリを学ぶ。
- そのデモの js を読んで、書き方を学ぶ。
これ以外の手段はないと思う。少なくとも Getting started や Layout extensionsにはそんなこと一言も書いてないんだから。
第一印象
「ドキュメントはヒドい」は重々わかった上で飛びついてるのでもとからハードルが低いんだけれど、という点は差し引いてワタシの話をきいてね。
印象は、「良い」。非常に。(異論を持たれるのを覚悟の上で)「滅茶苦茶簡単だ」し、Demos をざっと眺める限り、Graphviz に期待することの大抵のことは出来そうだし。
なので問題はワタシにとってはただ一つ。
前置きで書いたように『ほとんどの場合は他の何か(ワタシなら Python など)の助けを借りて生成することになるし』、ということはだ、「サーバサイドで自動生成」あるいは「PC で(Python などで)生成」ということをどうせするんだから、となれば、「別に Graphviz でよくね?」てことになるのね、「そこで Graphviz が使える限りは」。Graphviz は svg も吐き出せるからね。
なので「サーバで生成したいが Graphviz がインストールされてない」なら嬉しいてことになるわけだけれど、もし両方使えるとしたならば。個人的には Graphviz のフォント周りのダサさでいい思い出がないので、Graphviz 以外の選択肢が増えたことはとっても嬉しい。
こんな感じかな、第一印象は。