いまさら mermaid の xychart β版レビュー

# 0. はじめに

自分は Qiita でいわゆるグラフ（折れ線グラフや棒グラフ）を描くことが多いのですが，簡単なものでも EXCEL で作成したグラフをビットマップで貼り付けるしかないと思っていました。しかし，最近 Qiita でもサポートされている mermaid でも xychart といういわゆるグラフ（折れ線グラフや棒グラフ）を描く機能の β 版がテストされていることを知りました。

ということで，どこまで出来るのかテストしてみました。

# 1. こんな折れ線グラフを描きたい

EXCELで作成したグラフをビットマップで貼り付けています。

```plantuml
<style>
root {
  margin: 0;
  padding: 0;
}
title {
  fontSize: 17;
  fontStyle: normal;
}
</style>
title
<img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490655/7fe74772-5b01-fe4e-9262-60c9c638966b.png>
図１　四則演算で求める数と実現可能な組み合わせの数
end title
```

ただし，グラフの下側にある図のタイトルだけは  PlantUML で挿入しています。
※詳しいテクニックは下記の記事を参照下さい。

[Qiitaのmarkdownで画像にキャプション（タイトル）を付ける方法 - Qiita](https://qiita.com/TETSURO1999/items/5cbe35ef617adf46a5bb)

# 2. xychart β版で折れ線グラフを描く

mermaid を用いると，折れ線グラフは割と綺麗に描けます。ただし，データのX軸座標は等間隔である必要があります。

```mermaid
%%{
    init:{
        "xyChart":{
            "width":640,
            "height":400,
            "titleFontSize":17,
            "xAxis":{
                "titleFontSize":17,
                "labelFontSize":17,
                "axisLineWidth":1,
                "tickWidth":1,
                "showLabel":true
            },
            "yAxis":{
                "titleFontSize":17,
                "labelFontSize":17,
                "axisLineWidth":1,
                "tickWidth":1,
                "showLabel":true
            }
        },
        "themeVariables":{
            "fontFamily":"monospaced",
            "xyChart":{
                "plotColorPalette":"red"
            }
        }
    }
}%%
xychart-beta
title "図１　四則演算で求める数と実現可能な組み合わせの数"
x-axis "四則演算で求める数" 0 --> 50
y-axis "実現可能な組み合わせ数" 0 --> 60
line [55, 55, 55, 40, 39, 42, 42, 44, 45, 47, 43, 37, 38, 32, 27, 40, 35, 37, 28, 33, 35, 26, 15, 12, 31, 22, 22, 13, 18, 15, 32, 15, 20, 15, 14, 23, 28, 20, 4, 10, 23, 11, 20, 10, 7, 16, 9, 3, 28, 21, 23]
```

グラフの文字の大きさや色は細かく調整可能です。

````markdown
```mermaid
%%{
    init:{
        "xyChart":{
            "width":640,
            "height":400,
            "titleFontSize":17,
            "xAxis":{
                "titleFontSize":17,
                "labelFontSize":17,
                "axisLineWidth":1,
                "tickWidth":1,
                "showLabel":true
            },
            "yAxis":{
                "titleFontSize":17,
                "labelFontSize":17,
                "axisLineWidth":1,
                "tickWidth":1,
                "showLabel":true
            }
        },
        "themeVariables":{
            "fontFamily":"monospaced",
            "xyChart":{
                "plotColorPalette":"red"
            }
        }
    }
}%%
xychart-beta
title "図２　四則演算で求める数と実現可能な組み合わせの数"
x-axis "四則演算で求める数" 0 --> 50
y-axis "実現可能な組み合わせ数" 0 --> 60
line [55, 55, 55, 40, 39, 42, 42, 44, 45, 47, 43, 37, 38, 32, 27, 40, 35, 37, 28, 33, 35, 26, 15, 12, 31, 22, 22, 13, 18, 15, 32, 15, 20, 15, 14, 23, 28, 20, 4, 10, 23, 11, 20, 10, 7, 16, 9, 3, 28, 21, 23]
```
````

# 3. こんな棒グラフを描きたい

PlantUML のインライン SVG スプライトを用いて＊無理やり＊作成した棒グラフです。

```plantuml
@startuml
<style>
root {
  margin: 0;
  padding: 0;
}
title {
  fontStyle: normal
  fontSize: 17;
}
</style>
sprite FIGURE <svg width="600" height="380" viewbox="0 0 600 380">
<g fill="gray">
<path d="M65 20  h505 v1 h-505" />
<path d="M65 70  h505 v1 h-505" />
<path d="M65 120  h505 v1 h-505" />
<path d="M65 170 h505 v1 h-505" />
<path d="M65 220 h505 v1 h-505" />
<path d="M65 270 h505 v1 h-505" />
<path d="M65 320 h505 v1 h-505" />
<path d="M70  325 v-305 h1 v305" />
<path d="M120 325 v-305 h1 v305" />
<path d="M170 325 v-305 h1 v305" />
<path d="M220 325 v-305 h1 v305" />
<path d="M270 325 v-305 h1 v305" />
<path d="M320 325 v-305 h1 v305" />
<path d="M370 325 v-305 h1 v305" />
<path d="M420 325 v-305 h1 v305" />
<path d="M470 325 v-305 h1 v305" />
<path d="M520 325 v-305 h1 v305" />
<path d="M570 325 v-305 h1 v305" />
</g>
<text x="65"  y="340" fill="black" font-size="16">0</text>
<text x="115" y="340" fill="black" font-size="16">5</text>
<text x="160" y="340" fill="black" font-size="16">10</text>
<text x="210" y="340" fill="black" font-size="16">15</text>
<text x="260" y="340" fill="black" font-size="16">20</text>
<text x="310" y="340" fill="black" font-size="16">25</text>
<text x="360" y="340" fill="black" font-size="16">30</text>
<text x="410" y="340" fill="black" font-size="16">35</text>
<text x="460" y="340" fill="black" font-size="16">40</text>
<text x="510" y="340" fill="black" font-size="16">45</text>
<text x="560" y="340" fill="black" font-size="16">50</text>
<text x="55"  y="326" fill="black" font-size="16">0</text>
<text x="42"  y="276" fill="black" font-size="16">10</text>
<text x="42"  y="226" fill="black" font-size="16">20</text>
<text x="42"  y="176" fill="black" font-size="16">30</text>
<text x="42"  y="126" fill="black" font-size="16">40</text>
<text x="42"  y="76"  fill="black" font-size="16">50</text>
<text x="42"  y="26"  fill="black" font-size="16">60</text>
<text x="245" y="360" fill="black" font-size="16">四則演算で求める数</text>
<text x="15"  y="90"  fill="black" font-size="16">実</text>
<text x="15"  y="107" fill="black" font-size="16">現</text>
<text x="15"  y="124" fill="black" font-size="16">可</text>
<text x="15"  y="141" fill="black" font-size="16">能</text>
<text x="15"  y="158" fill="black" font-size="16">な</text>
<text x="15"  y="175" fill="black" font-size="16">組</text>
<text x="15"  y="192" fill="black" font-size="16">み</text>
<text x="15"  y="209" fill="black" font-size="16">合</text>
<text x="15"  y="226" fill="black" font-size="16">わ</text>
<text x="15"  y="243" fill="black" font-size="16">せ</text>
<text x="15"  y="260" fill="black" font-size="16">数</text>
<g fill="pink">
<path d="M68  320 v-275 h5 v275" />
<path d="M78  320 v-275 h5 v275" />
<path d="M88  320 v-275 h5 v275" />
<path d="M98  320 v-200 h5 v200" />
<path d="M108 320 v-195 h5 v195" />
<path d="M118 320 v-210 h5 v210" />
<path d="M128 320 v-210 h4 v210" />
<path d="M138 320 v-220 h5 v220" />
<path d="M148 320 v-225 h5 v225" />
<path d="M158 320 v-235 h5 v235" />
<path d="M168 320 v-215 h5 v215" />
<path d="M178 320 v-185 h5 v185" />
<path d="M188 320 v-190 h5 v190" />
<path d="M198 320 v-160 h5 v160" />
<path d="M208 320 v-135 h5 v135" />
<path d="M218 320 v-200 h5 v200" />
<path d="M228 320 v-175 h5 v175" />
<path d="M238 320 v-185 h5 v185" />
<path d="M248 320 v-140 h5 v140" />
<path d="M258 320 v-165 h5 v165" />
<path d="M278 320 v-130 h5 v130" />
<path d="M288 320 v-75  h5 v75" />
<path d="M298 320 v-60  h5 v60" />
<path d="M318 320 v-110 h5 v110" />
<path d="M328 320 v-110 h5 v110" />
<path d="M338 320 v-65  h5 v65" />
<path d="M348 320 v-90  h5 v90" />
<path d="M358 320 v-75  h5 v75" />
<path d="M378 320 v-75  h5 v75" />
<path d="M388 320 v-100 h5 v100" />
<path d="M398 320 v-75  h5 v75" />
<path d="M408 320 v-70  h5 v70" />
<path d="M418 320 v-115 h5 v115" />
<path d="M428 320 v-140 h5 v140" />
<path d="M438 320 v-100 h5 v100" />
<path d="M448 320 v-20  h5 v20" />
<path d="M458 320 v-50  h5 v50" />
<path d="M468 320 v-115 h5 v115" />
<path d="M478 320 v-55  h5 v55" />
<path d="M488 320 v-100 h5 v100" />
<path d="M498 320 v-50  h5 v50" />
<path d="M508 320 v-35  h5 v35" />
<path d="M518 320 v-80  h5 v80" />
<path d="M528 320 v-45  h5 v45" />
<path d="M538 320 v-15  h5 v15" />
<path d="M548 320 v-140 h5 v140" />
<path d="M558 320 v-105 h5 v105" />
<path d="M568 320 v-115 h5 v115" />
</g>
<g fill="red">
<path d="M268 320 v-175 h5 v175" />
<path d="M308 320 v-155 h5 v155" />
<path d="M368 320 v-160 h5 v160" />
</g>
<text x="260" y="140" fill="red" font-size="16">35</text>
<text x="300" y="160" fill="red" font-size="16">31</text>
<text x="360" y="155" fill="red" font-size="16">32</text>
</svg>
title
<$FIGURE>
図２　四則演算で求める数と実現可能な組み合わせの数
end title
@enduml
```

※詳しいテクニックは下記の記事を参照下さい。ただしオススメはしません。
[QiitaのmarkdownでSVGを使って作図する - Qiita](https://qiita.com/TETSURO1999/items/870962714724dde98651)

# 4. xychart β版で棒グラフを描く

mermaid を用いると棒グラフも綺麗に描けます。

```mermaid
%%{
    init:{
        "xyChart":{
            "width":640,
            "height":400,
            "titleFontSize":17,
            "xAxis":{
                "titleFontSize":17,
                "labelFontSize":17,
                "axisLineWidth":1,
                "tickWidth":1,
                "showLabel":true
            },
            "yAxis":{
                "titleFontSize":17,
                "labelFontSize":17,
                "axisLineWidth":1,
                "tickWidth":1,
                "showLabel":true
            }
        },
        "themeVariables":{
            "fontFamily":"monospaced",
            "xyChart":{
                "plotColorPalette":"pink,red"
            }
        }
    }
}%%
xychart-beta
title "図２　四則演算で求める数と実現可能な組み合わせの数"
x-axis "四則演算で求める数" [0,"​​","​‌","​⁠","​⁡",5,"​⁢","​⁣","​⁤","‌​",10,"‌‌","‌⁠","‌⁡","‌⁢",15,"‌⁣","‌⁤","⁠​","⁠‌",20,"⁠⁠","⁠⁡","⁠⁢","⁠⁣",25,"⁠⁤","⁡​","⁡‌","⁡⁠",30,"⁡⁡","⁡⁢","⁡⁣","⁡⁤",35,"⁢​","⁢‌","⁢⁠","⁢⁡",40,"⁢⁢","⁢⁣","⁢⁤","⁣​",45,"⁣‌","⁣⁠","⁣⁡","⁣⁢",50]
y-axis "実現可能な組み合わせ数" 0 --> 60
bar [55, 55, 55, 40, 39, 42, 42, 44, 45, 47, 43, 37, 38, 32, 27, 40, 35, 37, 28, 33, 35, 26, 15, 12, 31, 22, 22, 13, 18, 15, 32, 15, 20, 15, 14, 23, 28, 20, 4, 10, 23, 11, 20, 10, 7, 16, 9, 3, 28, 21, 23]
bar [-5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 35, -5, -5, -5, 31, -5, -5, -5, -5, -5, 32, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5]
```

これは特定の棒の色を変えたのではなく，ピンク色 `#ffc0cb` の棒グラフと赤色 `#ff0000` の棒グラフの二つを重ねています。色は `plotColorPalette` にて，個数分の色を羅列すれば良いようです。赤色 `#ff0000` の棒グラフは，強調箇所以外では見えないように値をマイナスにしています。

````markdown
```mermaid
%%{
    init:{
        "themeVariables":{
            "fontFamily":"monospaced",
            "xyChart":{
                "plotColorPalette":"pink,red"
            }
        }
    }
}%%
xychart-beta
title "図２　四則演算で求める数と実現可能な組み合わせの数"
x-axis "四則演算で求める数" [0,"​​","​‌","​⁠","​⁡",5,"​⁢","​⁣","​⁤","‌​",10,"‌‌","‌⁠","‌⁡","‌⁢",15,"‌⁣","‌⁤","⁠​","⁠‌",20,"⁠⁠","⁠⁡","⁠⁢","⁠⁣",25,"⁠⁤","⁡​","⁡‌","⁡⁠",30,"⁡⁡","⁡⁢","⁡⁣","⁡⁤",35,"⁢​","⁢‌","⁢⁠","⁢⁡",40,"⁢⁢","⁢⁣","⁢⁤","⁣​",45,"⁣‌","⁣⁠","⁣⁡","⁣⁢",50]
y-axis "実現可能な組み合わせ数" 0 --> 60
bar [55, 55, 55, 40, 39, 42, 42, 44, 45, 47, 43, 37, 38, 32, 27, 40, 35, 37, 28, 33, 35, 26, 15, 12, 31, 22, 22, 13, 18, 15, 32, 15, 20, 15, 14, 23, 28, 20, 4, 10, 23, 11, 20, 10, 7, 16, 9, 3, 28, 21, 23]
bar [-5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 35, -5, -5, -5, 31, -5, -5, -5, -5, -5, 32, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5]
```
````

全てのX軸目盛りを表示させると重なって鬱陶しいので間引いて表示させています。一見，間引いた目盛りは同じ空文字列に見えますが，目盛りの値が重複するとエラーになるので，実は見えない文字を組み合わせて全ての目盛りの値が重複しないようにしています。

<table>
<caption>表１　見えない Unicode 文字の例</caption>
<thead>
<tr><th>文字コード</th><th>説明</th></tr>
</thead>
<tbody>
<tr><td>U+200B</td><td>ZERO WIDTH SPACE</td></tr>
<tr><td>U+200C</td><td>ZERO WIDTH NON-JOINER</td></tr>
<tr><td>U+2060</td><td>WORD JOINER</td></tr>
<tr><td>U+2061</td><td>FUNCTION APPLICATION</td></tr>
<tr><td>U+2062</td><td>INVISIBLE TIMES</td></tr>
<tr><td>U+2063</td><td>INVISIBLE SEPARATOR</td></tr>
<tr><td>U+2064</td><td>INVISIBLE PLUS</td></tr>
</tbody>
</table>

0～50 までの間の見えない目盛りは 40 個ありますが，見えない Unicode 文字 7 種類を 2 個ずつ使用すれば 49 通りの重複しない見えない文字列が作れるので，このうち 40 個を使っています。

# 5. まとめ

今後の課題をまとめると下記のようになるでしょうか？

- グラフのタイトルが上側に固定されており，下側に表示できません
  ※他のチャートも同様なので改善される見込みは薄いように思います
- 折れ線グラフの線の太さを変更できません
- 棒グラフの棒の幅を変更できません
- 棒グラフの値がゼロのときも高さがあります（マイナスの値にしないと棒が消えません）
- X,Y 軸の目盛り間隔を指定できません
- グリッド表示できません
- 凡例を表示できません

# 6. 参考文献

- [Mermaid - XY Chart](https://mermaid.js.org/syntax/xyChart.html)
- [Invisible Characters - Unicode characters you can not see](https://invisible-characters.com/)

- [本当に大切なものは目に見えない ~Unicodeの目に見えない改行文字に苦しめられた話~Qiita](https://qiita.com/lilpacy/items/57a0257dbbf69f36ac05)