概要
blockdiagでフローチャートを描こうとするも、コレジャナイ出力が得られることが少なくない。
いろいろ使ってみる中で解決できた・できなかった事例について、記録を残していく。
ちょっとの修正で直せたもの
if分岐が横から出ない
状況
edge_layout=flowchart
を設定しているにも関わらず、if分岐がひし形の下から出てしまう。
回避策
ダミーのノードd
をb0
と横並びさせる。
これは、横から分岐を出すには2つのノードが横並びになっている必要があるため。
ダミーノードはshape=none
を使うのが無難。クラス化しておくと使いやすい。
ダミーノードには矢印が付いて欲しくないので、分岐側のエッジはdir=none
として頭を消しておく。
blockdiag{
orientation = portrait;
edge_layout = flowchart;
bp [shape=beginpoint];
lin [shape=flowchart.loopin];
c [shape=flowchart.condition];
b0 [shape=box];
lout [shape=flowchart.loopout];
ep [shape=endpoint];
class dummy [shape=none];
d [class=dummy];
// main
bp -> lin -> c -> b0 -> lout -> ep;
// break
c -> d -> ep [dir=none];
}
if分岐の左右が思い通りにならない
状況
ifの「そっちじゃない方(b0
)」が下に分岐し、とっても不格好になる。
ループを巻き込んじゃったりすると左右にずれてしまい、もう目も当てられない事態になる。
回避策
なんと、分岐の左右はノードを定義した順序に依存している模様。
というわけで、「分岐の真下に配置したいノード(b1
)」を分岐(c
)の直後に定義する。
こういうの、ちゃんとコードを読み漁って情報を集めたほうが良いかもしれない。
blockdiag{
orientation = portrait;
edge_layout = flowchart;
bp [shape=beginpoint];
lin [shape=flowchart.loopin];
c [shape=flowchart.condition];
// b1 -> b0
b1 [shape=box];
b0 [shape=box];
lout [shape=flowchart.loopout];
ep [shape=endpoint];
bp -> lin -> c -> b1 -> lout -> ep;
c -> b0 -> ep;
}
めっちゃ横に膨らむ
状況
分岐の仕方や数によってはフローチャートが横に膨らんでいく場合がある。
スライドの端にちょこっと載せるとか、縦長が嬉しい場合にちょっと直したくなる。
以下の終端が複数あるフローチャートを題材にしてみる。
回避策1:下に回り込ませる
1つめの終端(hoge
)から、2つめの終端への分岐の開始点(b1
)に見えないエッジ(style=none
)を引いてあげる。
この2ノードが縦に揃えられることで、レイアウトが変わる。
blockdiag{
orientation = portrait;
edge_layout = flowchart;
bp [shape=beginpoint];
lin [shape=flowchart.loopin];
c [shape=flowchart.condition];
b0 [shape=box];
b1 [shape=box];
lout [shape=flowchart.loopout];
ep0 [shape=endpoint, label="hoge"];
ep1 [shape=endpoint, label="fuga"];
// dummy
class dummy [shape=none];
d [class=dummy];
// main
bp -> lin -> c -> b0 -> lout -> ep0;
// break
c -> d [dir=none];
d -> b1 -> ep1;
// invisible edge
ep0 -> b1 [style=none];
}
回避策2:回り道を縮める
上図だが、回り道の矢印が膨らんでいてあまりダイエットできていない。
この「回り具合」はspan_width
及びnode_width
依存なので、これらを小さく設定する。
ただし、node_width
を縮めてノードまで細くなっては意味ないので、
ノードのサイズ設定に関してはclass
を定義してそちらにまとめて書いてやると良い。
blockdiag{
orientation = portrait;
edge_layout = flowchart;
node_width = 20;
span_width = 20;
class box [shape=box, width=128];
class if [shape=flowchart.condition, width=128];
class lin [shape=flowchart.loopin, width=128];
class lout [shape=flowchart.loopout, width=128];
bp [shape=beginpoint];
lin [class=lin];
c [class=if];
b0 [class=box];
b1 [class=box];
lout [class=lin];
ep0 [shape=endpoint, label="hoge"];
ep1 [shape=endpoint, label="fuga"];
class dummy [shape=none];
d [class=dummy, width=10];
// main
bp -> lin -> c -> b0 -> lout -> ep0;
// break
c -> d [dir=none];
d -> b1 -> ep1;
// invisible edge
ep0 -> b1 [style=none];
}
class
定義より上は「おまじない」として使いまわすのが望ましいかもしれない。
bp
とep
のラベルが潰れているが、これも適切なwidth
を設定すれば直せる。
どうにもならなさそうなもの
戻りの矢印が引けない
基本的に下から上(左から右)のノードに矢印を引くことが想定されていない模様。
そもそも戻り矢印なんか使わない努力をするべきかも。
- ループは
flowchart.loopin(loopout)
を使って書く - 折り返し(
folded
)は使わず、terminator
などをつかって2つ以上に区切る
左から回り込めない
もし出来る方法があったらマジで教えてほしい。
ただ、実際やるとなるとマッピングの難易度的な意味で開発者への負荷が爆上がりしそう。
文字数制限がキツい
特にflowchart.condition
などがそうだが、文字数制限がキツい。
また、エッジのラベルも同様(TとかFくらいしか書かないけど)。
横長いノードが嫌なら、height
を増やしてテキストを改行するのが無難か。
改行はlabel="1行目\n2行目"
のように書くと普通にできる。
まとめ
上手に使いこなせていないのでつらい。