|
| 1 | +--- |
| 2 | +title: "Mermaid.jsで数値報告のための簡易的なグラフを作るTips" |
| 3 | +date: 2026/04/17 00:00:00 |
| 4 | +postid: a |
| 5 | +tag: |
| 6 | + - mermaid.js |
| 7 | + - Markdown |
| 8 | +category: |
| 9 | + - Management |
| 10 | +thumbnail: /images/2026/20260417a/thumbnail.png |
| 11 | +author: 真野隼記 |
| 12 | +lede: "Markdownでプロジェクトの進捗報告やチームの振り返り資料をまとめていると、「ここにグラフがあれば一目で伝わるのに」という場面に出くわします。Mermaid.jsでグラフ化するとAIとの連携も便利でした。" |
| 13 | +mathjax: true |
| 14 | +--- |
| 15 | + |
| 16 | +## はじめに |
| 17 | + |
| 18 | +Markdownでプロジェクトの進捗報告やチームの振り返り資料をまとめていると、定量的な部分にはグラフを入れたくなります。Excelなど外部ツールでグラフを作成して画像を挿入しても良いですが、画像ファイルの管理がちと面倒です。 |
| 19 | + |
| 20 | +[Mermaid.js](https://mermaid.js.org/) はUMLを描けることで有名ですが、実はいくつかのグラフ表示もサポートされています。どうせあまりオシャレじゃないんでしょう?..と、あまり期待していなかったのですが、想定よりオシャレ化ができることが分かったので、この感動を伝えさせてください。 |
| 21 | + |
| 22 | +もちろん、見た目や構成ではいくつか制約があります。それさえ許容できれば、テキストでグラフを記述でき、VS Codeなどでのプレビュー以外にも、GitHub・GitLab・Notionなど多くのプラットフォームでプレビューできますし、何よりAIからの支援も受けやすくなりお勧めです。 |
| 23 | + |
| 24 | +試してみたナレッジをいくつか紹介します。 |
| 25 | + |
| 26 | +## 環境 |
| 27 | + |
| 28 | +- Mermaid.js v11+(`radar-beta`、`xychart-beta`が利用可能) |
| 29 | +- 表示確認: VS Code(Markdown Preview Mermaid Support拡張)、GitHub |
| 30 | + |
| 31 | +## レーダーチャート |
| 32 | + |
| 33 | +2025年3月にリリースされた[v11.6](https://github.com/mermaid-js/mermaid/releases/tag/mermaid%4011.6.0)からレーダーチャートが利用可能になりました。[ドキュメント](https://mermaid.ai/open-source/syntax/radar.html)もあります。レーダーチャートは、多軸の評価結果を一目で比較したいといった用途に便利ですよね。 |
| 34 | + |
| 35 | +### Tips 1: レーダーチャートの装飾 |
| 36 | + |
| 37 | +例えば、チームの「開発チーム成熟度」を複数の観点で評価し、2つのチームの強みを重ねて比較してみます。 |
| 38 | + |
| 39 | +このとき、以下の設定がおすすめです。デフォルトでもそこそこオシャレですが、細かい調整をしたくなります。 |
| 40 | + |
| 41 | +1. `graticule polygon` を指定して目盛線を多角形にする |
| 42 | + - デフォルトの曲線もオシャレだが、言いたいことが伝わりにくい... |
| 43 | +2. 絶対評価の基準となる `max`(満点)と `min`(最低点)を指定する |
| 44 | + - 指定しない場合は、入力から自動で補正するが揃えた方が無難 |
| 45 | +3. `curve` のラベルにチーム名だけでなく、括弧書きで「平均スコア」等のサマリを埋め込んで凡例とする |
| 46 | + - テキストでの追加情報は、ラベルに足すしかない |
| 47 | +4. デフォルトの配色を変えたい場合、configで変更可能 |
| 48 | + - `cScale0`/`cScale1`で1番目、2版目のレーダーの色を調整。 `curveOpacity` で透過度を指定する |
| 49 | + |
| 50 | +```mermaid |
| 51 | +--- |
| 52 | +config: |
| 53 | + theme: default |
| 54 | + themeVariables: |
| 55 | + cScale0: "#FF5252" |
| 56 | + cScale1: "#4CAF50" |
| 57 | + radar: |
| 58 | + axisColor: "#9E9E9E" |
| 59 | + graticuleColor: "#E0E0E0" |
| 60 | + curveOpacity: 0.25 |
| 61 | + curveStrokeWidth: 1 |
| 62 | +--- |
| 63 | +radar-beta |
| 64 | + graticule polygon |
| 65 | + axis v["ベロシティ"], q["品質"], a["自律性"] |
| 66 | + axis c["コミュ力"], p["計画精度"], t["技術力"] |
| 67 | + curve d["チームA (4.4)"]{4.4, 4.2, 4.8, 4.7, 3.9, 4.3} |
| 68 | + curve c["チームB (4.2)"]{4.5, 3.7, 4.5, 3.9, 4.8, 4.4} |
| 69 | + max 5 |
| 70 | + min 0 |
| 71 | +``` |
| 72 | + |
| 73 | +```c |
| 74 | +--- |
| 75 | +config: |
| 76 | + theme: default |
| 77 | + themeVariables: |
| 78 | + cScale0: "#FF5252" |
| 79 | + cScale1: "#4CAF50" |
| 80 | + radar: |
| 81 | + axisColor: "#9E9E9E" |
| 82 | + graticuleColor: "#E0E0E0" |
| 83 | + curveOpacity: 0.25 |
| 84 | + curveStrokeWidth: 1 |
| 85 | +--- |
| 86 | +radar-beta |
| 87 | + graticule polygon |
| 88 | + axis v["ベロシティ"], q["品質"], a["自律性"] |
| 89 | + axis c["コミュ力"], p["計画精度"], t["技術力"] |
| 90 | + curve d["チームA (4.4)"]{4.4, 4.2, 4.8, 4.7, 3.9, 4.3} |
| 91 | + curve c["チームB (4.2)"]{4.5, 3.7, 4.5, 3.9, 4.8, 4.4} |
| 92 | + max 5 |
| 93 | + min 0 |
| 94 | +``` |
| 95 | +
|
| 96 | +## 棒グラフ |
| 97 | +
|
| 98 | +### Tips 2: 積み上げグラフの実現 |
| 99 | +
|
| 100 | +xychart-betaは ネイティブの積上げ棒グラフをサポートしていません。複数の`bar`シリーズを定義すると、並列ではなく**重ね描画**されます。 |
| 101 | +
|
| 102 | +例として、機能別・優先度別の残タスク数を可視化したいとします。 |
| 103 | +
|
| 104 | +| | 検索機能 | 決済機能 | ユーザー管理 | |
| 105 | +|---|---|---|---| |
| 106 | +| 優先度:高 | 0 | 2 | 0 | |
| 107 | +| 優先度:中 | 2 | 4 | 3 | |
| 108 | +| 優先度:低 | 4 | 0 | 1 | |
| 109 | +| **合計** | **6** | **6** | **4** | |
| 110 | +
|
| 111 | +素朴にそのまま書くと、本来「6」「6」「4」の高さになるはずの棒グラフが、ただ同じ位置から重ねて描画されてしまい、意味不明な状態になります(積み上げグラフになっているじゃん...と思いますが、高さをよく見ると合計値に達していません)。 |
| 112 | +
|
| 113 | +```mermaid |
| 114 | +xychart-beta |
| 115 | + title "❌️重なって描画される" |
| 116 | + x-axis ["検索機能", "決済機能", "ユーザー管理"] |
| 117 | + y-axis "タスク数" 0 --> 10 |
| 118 | + bar "高" [0, 2, 0] |
| 119 | + bar "中" [2, 4, 3] |
| 120 | + bar "低" [4, 0, 1] |
| 121 | +``` |
| 122 | + |
| 123 | +```c |
| 124 | +xychart-beta |
| 125 | + title "NG: そのままの数値(重なって描画される)" |
| 126 | + x-axis ["検索機能", "決済機能", "ユーザー管理"] |
| 127 | + y-axis "タスク数" 0 --> 10 |
| 128 | + bar "高" [0, 2, 0] |
| 129 | + bar "中" [2, 4, 3] |
| 130 | + bar "低" [4, 0, 1] |
| 131 | +``` |
| 132 | + |
| 133 | +3本のグラフが重なっていますが、逆手にとって考えると、累積値で、擬似的に積上げ棒グラフにできるということです。悪い回避策だという指摘はいったん脇に..。 |
| 134 | + |
| 135 | +棒グラフは "最後"に書いた定義が "手前" に表示されます。そのため、一番最初に積み上げたい「低」を最初に書いて、「高」を最後に書きます。 |
| 136 | + |
| 137 | +- $ 低 = 高 + 中 + 低$ |
| 138 | +- $ 中 = 高 + 中$ |
| 139 | +- $ 高 = 高$ |
| 140 | + |
| 141 | +こうすると、「中」の棒は「低」の棒の「内側」に重なり、「高」の棒はさらにその内側に重なります。結果として**色が層になり、積上げに見える**わけです。 |
| 142 | + |
| 143 | +```mermaid |
| 144 | +xychart-beta |
| 145 | + title "✅️積み上げには成功、❌️0件が微妙な表示" |
| 146 | + x-axis ["検索機能", "決済機能", "ユーザー管理"] |
| 147 | + y-axis "タスク数" 0 --> 10 |
| 148 | + bar "低" [6, 6, 4] |
| 149 | + bar "中" [2, 6, 3] |
| 150 | + bar "高" [0, 2, 0] |
| 151 | +``` |
| 152 | + |
| 153 | +```c |
| 154 | +xychart-beta |
| 155 | + # ...中略... |
| 156 | + bar "低" [6, 6, 4] |
| 157 | + bar "中" [2, 6, 3] |
| 158 | + bar "高" [0, 2, 0] |
| 159 | +``` |
| 160 | + |
| 161 | +積み上げは成功しましたが、0件である「高」が微妙に表示されてしまいノイジーです(0なのにわずかに表示されてしまってます)。いろいろ試したのですが、配列の中間の0は `-1` に置換することで回避可能です。末尾の記述も-1にするか省略で回避できました。`-1` にしておくことで、グラフ上にはレンダリングされませんが、「データが存在する」という判定になるため、色の割当順序が正しく維持されるため、都合が良いです。 |
| 162 | + |
| 163 | +```mermaid |
| 164 | +xychart-beta |
| 165 | + title "✅️ 意図した通りに疑似積上げされる" |
| 166 | + x-axis ["検索機能", "決済機能", "ユーザー管理"] |
| 167 | + y-axis "タスク数" 0 --> 10 |
| 168 | + bar "低" [6, 6, 4] |
| 169 | + bar "中" [2, 6, 3] |
| 170 | + bar "高" [-1, 2] |
| 171 | +``` |
| 172 | + |
| 173 | +```c |
| 174 | +xychart-beta |
| 175 | + x-axis ["検索機能", "決済機能", "ユーザー管理"] |
| 176 | + # ...中略... |
| 177 | + bar "高" [-1, 2] ← 中間は-1、末尾は省略でも良い |
| 178 | +``` |
| 179 | + |
| 180 | +### Tips 3: 色の指定は plotColorPalette と凡例 |
| 181 | + |
| 182 | +さきほど、積み上げ棒グラフ化には成功しましたが、優先度が高い順に、目立たせたいと思うはずです。疑似積上げでは「外側ほど薄く、内側ほど濃く」するのが自然です。「高」を最も濃い色にすると、対応すべきタスクが視覚的に目立ちます。棒グラフの色は`plotColorPalette`で指定します。シリーズの定義順(`bar`の記述順)に対応します。 |
| 183 | + |
| 184 | +色を付けると、色の意味は何だ?となりますが、xychart-betaには凡例機能はありません(!)。そのため、Markdownが許容する環境であれば、Mermaidブロックのすぐ下にHTML書いてしまうのがてっとり早い回避手段です。 |
| 185 | + |
| 186 | +```mermaid |
| 187 | +--- |
| 188 | +config: |
| 189 | + theme: base |
| 190 | + themeVariables: |
| 191 | + xyChart: |
| 192 | + plotColorPalette: "#fff4dd, #ffd8b1, #FF6E40" |
| 193 | +--- |
| 194 | +xychart-beta |
| 195 | + x-axis ["検索機能", "決済機能", "ユーザー管理"] |
| 196 | + y-axis "タスク数" 0 --> 10 |
| 197 | + bar "低" [6, 6, 4] |
| 198 | + bar "中" [2, 6, 3] |
| 199 | + bar "高" [-1, 2] |
| 200 | +``` |
| 201 | + |
| 202 | +<div style="display: flex; justify-content: center; gap: 24px; font-size: 14px; color: #424242; font-family: sans-serif; margin-top: -8px;"> |
| 203 | + <div style="display: flex; align-items: center; gap: 6px;"> |
| 204 | + <span style="color: #FF6E40; font-size: 18px;">■</span> 高 |
| 205 | + </div> |
| 206 | + <div style="display: flex; align-items: center; gap: 6px;"> |
| 207 | + <span style="color: #ffd8b1; font-size: 18px;">■</span> 中 |
| 208 | + </div> |
| 209 | + <div style="display: flex; align-items: center; gap: 6px;"> |
| 210 | + <span style="color: #fff4dd; font-size: 18px; text-shadow: 0 0 1px #ccc;">■</span> 低 |
| 211 | + </div> |
| 212 | +</div> |
| 213 | + |
| 214 | +<br> |
| 215 | + |
| 216 | +```c |
| 217 | +--- |
| 218 | +config: |
| 219 | + theme: base |
| 220 | + themeVariables: |
| 221 | + xyChart: |
| 222 | + plotColorPalette: "#fff4dd, #ffd8b1, #FF6E40" |
| 223 | +--- |
| 224 | +xychart-beta |
| 225 | +... |
| 226 | + bar "低" [6, 6, 4] ← 1番目(#fff4dd: 薄い黄色) |
| 227 | + bar "中" [2, 6, 3] ← 2番目(#ffd8b1: 薄いオレンジ) |
| 228 | + bar "高" [-1, 2] ← 3番目(#FF6E40: 濃いオレンジ) |
| 229 | +``` |
| 230 | + |
| 231 | +HTMMLは以下のようなものを、mermaid.jsのすぐ下にそのまま配置します。 |
| 232 | + |
| 233 | + |
| 234 | +```html |
| 235 | +<div style="display: flex; justify-content: center; gap: 24px; font-size: 14px; color: #424242; font-family: sans-serif; margin-top: -8px;"> |
| 236 | + <div style="display: flex; align-items: center; gap: 6px;"> |
| 237 | + <span style="color: #FF6E40; font-size: 18px;">■</span> 高 |
| 238 | + </div> |
| 239 | + <div style="display: flex; align-items: center; gap: 6px;"> |
| 240 | + <span style="color: #ffd8b1; font-size: 18px;">■</span> 中 |
| 241 | + </div> |
| 242 | + <div style="display: flex; align-items: center; gap: 6px;"> |
| 243 | + <span style="color: #fff4dd; font-size: 18px; text-shadow: 0 0 1px #ccc;">■</span> 低 |
| 244 | + </div> |
| 245 | +</div> |
| 246 | +``` |
| 247 | + |
| 248 | +ポイントは、薄い色(優先度「低」)の凡例の四角(■)に `text-shadow: 0 0 1px #ccc;` を付けて輪郭線を出すことです。これにより、白背景でも凡例の視認性をしっかり確保できます。 |
| 249 | + |
| 250 | +### Tips 4: Before/Afterの表示 |
| 251 | + |
| 252 | +xychart-betaはグループ化(横並べ)ができません。そのため、リファクタリング前(Before)と後(After)のバグ発生数を比較したい場合などは、グラフを2つ並べます。 |
| 253 | + |
| 254 | +```mermaid |
| 255 | +--- |
| 256 | +config: |
| 257 | + theme: base |
| 258 | + themeVariables: |
| 259 | + xyChart: |
| 260 | + plotColorPalette: "#FF8A80" |
| 261 | +--- |
| 262 | +xychart-beta |
| 263 | + title "バグ発生数 (リファクタリング前)" |
| 264 | + x-axis ["検索機能", "決済機能", "ユーザー管理", "共通基盤"] |
| 265 | + y-axis "件数" 0 --> 80 |
| 266 | + bar [8, 39, 41, 24] |
| 267 | +``` |
| 268 | + |
| 269 | +```mermaid |
| 270 | +--- |
| 271 | +config: |
| 272 | + theme: base |
| 273 | + themeVariables: |
| 274 | + xyChart: |
| 275 | + plotColorPalette: "#81C784" |
| 276 | +--- |
| 277 | +xychart-beta |
| 278 | + title "バグ発生数 (リファクタリング後)" |
| 279 | + x-axis ["検索機能", "決済機能", "ユーザー管理", "共通基盤"] |
| 280 | + y-axis "件数" 0 --> 80 |
| 281 | + bar [0, 8, 70, 34] |
| 282 | +``` |
| 283 | + |
| 284 | +ポイントは**Y軸の上限を揃えること**(`0 --> 80`)です。これにより、棒の長さだけで直感的に「改善したかどうか」を比較できるようになります。 |
| 285 | + |
| 286 | +## おわりに |
| 287 | + |
| 288 | +Mermaid.jsは「テキストで書ける手軽さ」が最大の強みですが、積上げ棒グラフや凡例、スライスの順序制御といった実務で欲しい機能に一部制約があります。 |
| 289 | + |
| 290 | +しかし、今回紹介した**疑似積上げ・-1置換・HTML凡例・上下2段比較**といったテクニックを使えば、これらの制約を回避して、メンテナンス性の高い「それっぽい」レポートをMarkdown内で完結させることができます。 |
| 291 | + |
| 292 | +特にAIツールとの相性は抜群です。「このタスクデータをMermaidの疑似積上げ棒グラフにして」と頼めば、累積値の計算からコード生成まで一瞬で終わります。ぜひ、日々の進捗報告や振り返り資料に取り入れてみてください。 |
0 commit comments