svg-diagram について
svg-diagramは、文書用のSVG図を作成するための規約集です。明瞭で保守しやすい図を作る人向けに、レイアウト、間隔、コネクター、フォント、検証方法を定めています。
主な機能
- 01SVGファイルの配置と参照方法
- 02レイアウトと間隔の基準
- 03コネクターと矢印の規則
- 04文字幅とラベル配置の指針
- 05CJK対応フォントの宣言要件
活用シーン
- 01Markdown文書のフローチャート作成
- 02システムアーキテクチャ図の作成
- 03SVGの配置と読みやすさの確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bybit-exchange/ svg-diagram --skill svg-diagramインストール後、Claude Code で/svg-diagramを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.gitignoreLICENSEpackage.jsonREADME.mdtools/svg-lint/README.mdtools/svg-lint/bin/svg-lint.mjstools/svg-lint/lib/color.mjsformat-text.mjsregistry.mjspalette.mjslint.mjsformat-json.mjspanels.mjsgeometry.mjsparse-svg.mjsreport.mjstext-metrics.mjsdocument.mjstools/svg-lint/lib/checks/baseline-offset.mjsbox-height.mjsblock-spacing.mjsarrow-marker.mjsconnector-geometry.mjsxml-escaping.mjsviewbox-clipping.mjsfont-stack.mjstext-overflow.mjslight-bg-fallback.mjspalette-conformance.mjsoverlap.mjs詳細
SVG 図表作成の規約
出力先と参照方法
図表は SVG で作成し、ASCII アートは使いません。このルールで図を描くかどうかを決めます。このスキルでは、ファイルの配置先から始めて、図の作成方法を説明します。
- ドキュメントと同じ場所にある
assets/ディレクトリにファイルを配置します(例:docs/foo.md→docs/assets/foo-arch.svg) - Markdown から相対パス
で参照します。SVG XML をインラインで記述しないでください。 - ドキュメント内のデータを変更した場合は、対応する SVG も更新する必要があります。図と隣接する説明文が矛盾するのは、図がないよりも悪いことです。
基本原則
最初の作成で正確に仕上げる
最初に生成する SVG は、このドキュメントの末尾にある検証チェックリストのすべての項目を満たしている必要があります。間隔、パディング、配置、viewBox による切り抜きなど、基本的なレイアウトの問題を修正するために、ユーザーからのフィードバックに頼らないでください。生成後はチェックリストを自分で確認し、見つかった問題を修正してから結果を提示します。
要素を重ねない
- テキストをボックスや線に重ねないでください。
- 線がボックスを貫かないようにします(そのボックスに向かって終端する矢印の場合を除きます)。
- テキストと線の間には 10~20px の間隔を空けます。
- 隣接するボックス間の間隔については、後述の「ブロック間隔」セクションを参照してください(標準値は 25px 以上、推奨値は 25~30px です)。
- 色分けの凡例は図の本体の外側(下または横)に配置し、コンテンツ領域に重ねないでください。
<path d="M35,200 C 35,120 ..." .../>
<text x="55" y="200">Label text</text>
<text x="35" y="200">Label text</text>
視覚的なバランス
左右の半分で視覚的な重みが同程度になるようにし、注釈ボックスを追加または削除してバランスを取ります。
レイアウトのルール
中央揃え
content width = right edge of rightmost element - left edge of leftmost element
left margin = (viewBox width - content width) / 2
タイトルは viewBox の中央ではなく、コンテンツの中央に揃えます(コンテンツが非対称の場合、両者は異なります)。
<text x="[content center x]" y="[top_padding + font_ascent]" text-anchor="middle">Title</text>
コンテンツが左右対称の場合に限り、content center x = viewBox width / 2 となります。非対称の場合は、<g transform="translate(...)"> でグループ全体を中央に配置し、タイトルの x も新しいコンテンツの中央に合わせて更新します。
後から全体を移動する
SVG の完成後に左右(または上下)のパディングの非対称に気付いた場合でも、すべての座標を変更する必要はありません。コンテンツを <g transform="translate(dx, dy)"> で囲みます。
<svg viewBox="0 0 800 460" ...>
<defs>...</defs>
<g transform="translate(22, 0)">
</g>
</svg>
オフセットの計算方法:dx = (right padding - left padding) / 2。パディングとは、viewBox の端から最も近いコンテンツ要素までの距離です。
dx > 0:コンテンツを右に移動します(コンテンツが左に寄りすぎている場合に使用)dx < 0:コンテンツを左に移動します(コンテンツが右に寄りすぎている場合に使用)
使用する場面:コンテンツ全体が中央からずれており、すべての x 座標を編集したくない場合です。欠点:ファイル内の座標と実際に描画される位置が一致しなくなるため、後から編集する際にオフセットを頭の中で差し引く必要があります。大規模なレイアウト変更を予定している場合は、オフセットを個々の座標に反映し、<g> を削除します。
viewBox の余白
タイトルもコンテンツの一部であるため、上下の余白はタイトルを基準に測ります。
title y = margin + font ascent (≈ font-size × 0.75)
viewBox height = bottom y of content + margin
推奨余白:20~25px
<svg viewBox="0 0 680 295" ...>
<text x="340" y="32" font-size="16">Title</text>
...
</svg>
ボックスのレイアウト
- 同じ行にあるボックスのサイズ差は 60px 以下にします。テキストは中央揃えにします(
text-anchor="middle")。 - 同じ列にあるボックスは中心線を揃えます。
- 外側のボックスで内側のボックスを完全に囲みます:
outer size = content size + padding × 2
破線のグループ化ボックス(コンテナー)
関連するボックスをまとめるために使用します(例:「サーバー」、「クライアント」、「従業員のインスタンス」)。
スタイルの一貫性:1 つの図では、すべての破線のグループ化ボックスで次の属性を統一します。
stroke-dasharray(推奨値:6,4)rx(角の丸み。推奨値:8~12)fill(推奨値:#f8fafcまたはnone)- 内側の余白(推奨値:15~20px)
- タイトルのフォントサイズ(推奨値:11px。ボックス本文のテキストの12pxと区別できます)
タイトルの配置:グループタイトルはボックスの左上の内側(x = box x + 10, y = box y + 14)に、セカンダリテキストカラー#64748bを使用して配置します。
垂直方向の中央揃えに関する注意点:ボックスだけでなく、タイトルと内側のコンテンツを合わせた高さを基準に、グループボックスの垂直位置を計算します。タイトルがある場合、ボックス上部の約20~25pxがタイトル用に使われるため、内側のボックスはその下から始まります。
<rect x="50" y="100" width="200" height="120" rx="10"
stroke="#94a3b8" stroke-dasharray="6,4" fill="#f8fafc"/>
<text x="60" y="114" font-size="11" fill="#64748b">Server</text>
<rect x="65" y="125" width="170" height="36" rx="6" .../>
<rect x="65" y="170" width="170" height="36" rx="6" .../>
グループを指すコネクター:コネクターの論理的な対象が特定の要素ではなく要素群である場合、単一の要素ではなくグループボックスの境界で終端させます。または、要素をグループ化ボックスで囲み、そのボックスを矢印の終点にします。
ボックスの寸法
内側に十分な余白を確保できるよう、フォントサイズを基準にボックスの高さを決めます。
| コンテンツ | 高さの計算式 | 例(フォントサイズ12px) |
|---|---|---|
| 1行 | font-size × 3 | 36px |
| 2行 | font-size × 3 + 行の高さ | 36 + 18 = 54px |
| 複数行 | font-size × 3 + (行数 - 1) × 行の高さ | 追加の1行につき+18px |
計算式の由来:font-size × 3 = 上余白(≈font-size)+ 字形の高さ(≈font-size)+ 下余白(≈font-size)です。標準外のフォントサイズの場合も、同じ比率で調整します。
推奨行の高さ:font-size × 1.5(例:フォントサイズ12pxの場合は18px)
ボックス内でテキストを垂直方向に中央揃えする(ベースラインの配置)
SVGでは、<text y=...>のyは字形の上端ではなく、ベースラインを示します。ボックス内でテキストを視覚的に中央揃えするには、次のようにします。
text y = box center y + font-size × 0.35
= box y + box height/2 + font-size × 0.35
0.35という係数は、「字形の視覚的な中心からベースラインまで」の経験値です(フォントサイズの約3分の1)。
2つの係数を混同しないでください。
font-size × 0.75(アセント):タイトルなど、上から配置する要素に使用します(y = 上余白 + アセント)font-size × 0.35(ベースラインオフセット):ボックス内で垂直方向に中央揃えする場合に使用します
<rect x="30" y="50" width="110" height="36" rx="6" .../>
<text x="85" y="72" ...>Single line</text>
<rect x="30" y="50" width="110" height="54" rx="6" .../>
<text x="85" y="70" ...>First line</text>
<text x="85" y="88" ...>Second line</text>
表示サイズ
<svg viewBox="0 0 750 400" width="750" xmlns="http://www.w3.org/2000/svg">
| 図の種類 | 幅 |
|---|---|
| シンプルなリスト | 400px |
| フローチャート | 600~700px |
| アーキテクチャ図 | 700~800px |
コネクターのルール
コネクターの選択
同軸の接続には直線のLを使用します。経路が曲がる、または何かを迂回する場合は、常に滑らかなC/Q曲線を使用します。直角の折れ曲がりは使用しないでください。
<path d="M190,77 L 320,77" .../>
<path d="M130,145 L 130,213" .../>
<path d="M100,100 L100,200 L200,200" .../>
<path d="M100,100 C 100,150 150,200 200,200" .../>
| ケース | 推奨 | 構文 |
|---|---|---|
| 同軸(水平/垂直) | L | L endx,endy |
| 単純な曲がり | Q | Q ctrlx,ctrly endx,endy |
| S字カーブ/複雑な経路 | C | C ctrl1x,ctrl1y ctrl2x,ctrl2y endx,endy |
矢印のルール
- 方向はパスの最後のセグメントで決まります:右向きは x が増加し、下向きは y が増加します
- 対称な間隔:矢印と始点のボックスの間を 5px にし、終点のボックスでも同じ見た目の間隔を確保します
- ラベルは中央揃え:
x = (source right edge + target left edge) / 2とtext-anchor="middle"を使用します
曲線パスで矢印の向きを修正する方法:orient="auto" は、パス終点の接線に合わせて矢印の先端を配置します。C/Q 曲線の終点の接線は斜めになることがあり、矢印の先端が傾いて見える原因になります。修正方法:2 つ目の制御点(cp2)を、cp2 → end point の方向が矢印の先端を向けたい方向と正確に一致するように配置します。
<path d="M100,100 C 100,200 250,200 300,250" marker-end="url(#arrow)"/>
<path d="M100,100 C 100,200 300,220 300,250" marker-end="url(#arrow)"/>
<path d="M100,100 C 100,200 270,250 300,250" marker-end="url(#arrow)"/>
矢印の方向を制御するルール:
| 目標の方向 | cp2 の条件 | 例 |
|---|---|---|
| ↓ 下 | cp2.x = end.x, cp2.y < end.y | C ...,... ex,ey-20 ex,ey |
| → 右 | cp2.y = end.y, cp2.x < end.x | C ...,... ex-20,ey ex,ey |
| ← 左 | cp2.y = end.y, cp2.x > end.x | C ...,... ex+20,ey ex,ey |
| ↑ 上 | cp2.x = end.x, cp2.y > end.y | C ...,... ex,ey+20 ex,ey |
パスの終点の計算(間隔 5px、矢印の先端は線の終点より 6px 先まで伸びます):
基本ルール:始点は始点のボックスから 5px 離し、終点は終点のボックスから 11px 離します(間隔 5px + 矢印の先端の延長 6px)。
refX="2"(矢印の先端のくぼみ部分)を使用するため、線の終点より先端が 6px(8-2=6)先まで伸びます。また、線はくぼみの中央で矢印の先端につながるため、接続が連続して見えます。
4 方向の計算式:
| 方向 | 始点 | 終点 |
|---|---|---|
| → 右 | 始点のボックスの右端 + 5 | 終点のボックスの左端 - 11 |
| ← 左 | 始点のボックスの左端 - 5 | 終点のボックスの右端 + 11 |
| ↓ 下 | 始点のボックスの下端 + 5 | 終点のボックスの上端 - 11 |
| ↑ 上 | 始点のボックスの上端 - 5 | 終点のボックスの下端 + 11 |
<path d="M185,70 L 209,70" marker-end="url(#arrow)"/>
<path d="M215,70 L 191,70" marker-end="url(#arrow)"/>
<path d="M130,145 L 130,159" marker-end="url(#arrow)"/>
<path d="M130,165 L 130,151" marker-end="url(#arrow)"/>
双方向の例(ボックス間を上下両方向に矢印が伸びる例):
<path d="M320,380 L 320,409" marker-end="url(#arrow)"/>
<path d="M480,415 L 480,386" marker-end="url(#arrow)"/>
障害物を避ける経路
迂回経路は、障害物の境界から少なくとも 20px 離してください:
<path d="M600,313 Q 650,313 650,400 Q 650,640 635,685"
fill="none" stroke="#a855f7" stroke-dasharray="6,4" marker-end="url(#arrow)"/>
ブロック間隔(共通の単一基準)
隣接するボックス/ブロックの間隔は 25px 以上、25~30px を推奨します。
内訳:始点の間隔 5px + 終点の間隔と矢印の先端の延長 11px + 見える線分 6px 以上 + 安全余裕 ≈ 25px。見える線分は 6px 以上にしてください。それより短いと、矢印が点のようになります。
コンパクトに保つ:30px を超えないようにしてください。間隔が広すぎる(>40px)と、図全体が間延びし、接続線も長くなりすぎます。両端は 5px/11px、間の見える線分は 6~12px を目安にしてください。
全体の密度:作業が終わったら少し離れて密度を確認してください。コンテンツ領域が viewBox に比べて明らかに小さい(大きな空白領域がある)場合は、間隔を狭めるか、viewBox を小さくしてください。よくある原因:ボックス間隔が 30px を超えている、viewBox の余白が 25px を超えている、グループ化されたボックス内の余白が大きすぎる。
この文書でブロック間隔の基準はこれだけです。「要素を重ねない」と検証チェックリストの両方が、この基準を参照します。
SVG の描画順(z-order)
SVG に z-index はありません。後から描画された要素が手前に表示されます。次の順に配置してください:
<rect ... stroke-dasharray="6,4" fill="#f8fafc"/>
<path d="..." marker-end="url(#arrow)"/>
<rect ... fill="#dbeafe"/>
<text ...>Label</text>
よくある間違い:接続線を先に描画し、その後に破線の背景ボックスを描画すると、接続線が隠れてしまいます。
例外:レイヤーをまたぐループバック線:複数のボックスにまたがる必要がある接続線(反復ループ、領域をまたぐ破線など)は、ボックスの後(レイヤー 4)に描画してください。そうしないと、ボックスに隠れてしまいます:
<path d="..." stroke-dasharray="6,4" marker-end="url(#arrow-purple)"/>
テキスト幅の見積もり(はみ出し防止)
テキストを配置する前に、右端の位置を見積もり、隣接する要素に重ならないことを確認してください。
| フォントサイズ | ラテン文字の幅(概算) | CJK文字の幅(概算) |
|---|---|---|
| 8px | 4.5px | 8px |
| 9px | 5.0px | 9px |
| 10px | 5.5px | 10px |
| 11px | 6.0px | 11px |
| 12px | 7.0px | 12px |
見積もり式:
text-anchor="start":右端 ≈ x + 文字数 × 文字幅text-anchor="middle":左端/右端 ≈ x ± (文字数 × 文字幅) / 2text-anchor="end":左端 ≈ x - 文字数 × 文字幅
配置する前に確認してください:テキストの右端 + 10px < 右隣の要素の左端。
<text x="274" y="115" font-size="9">4K tokens (= mini-batch)</text>
<text x="154" y="138" font-size="9" text-anchor="middle">4K tokens (= mini-batch)</text>
曲線上のラベルの配置
円弧や曲線を説明するラベルは、経路上に置かないでください(線がテキストを横切ってしまいます)。曲線の凸側または凹側に配置してください。
<text x="350" y="218">Skip Connection</text>
<path d="M82,165 C 82,225 620,225 646,225" .../>
<text x="350" y="222">Skip Connection</text>
<path d="M82,149 C 82,260 600,255 640,255" .../>
ルール:ラベルと曲線上の最も近い点との間を15px以上空けてください。下向きに曲がる曲線の場合は上側に、上向きに曲がる曲線の場合は下側にラベルを配置してください。
座標の管理
コメントに境界を記録する
<rect x="280" y="55" width="340" height="435" .../>
要素を移動するときは、以下も連動して更新する
- viewBoxの寸法
- その要素への/その要素からのすべての矢印(始点、終点、制御点)
- 関連するラベルの位置
- その要素を囲む破線の背景/グループ化ボックス(スイムレーン、コンテナー)—最も更新を忘れやすい項目です
- 同じ行/列で位置を揃えているその他のボックス
- 影響を受けるその他の要素
スタイルのルール
フォント(必須)
すべてのSVGで、<style>内にCJK対応のフォントスタックを宣言してください。これは必須です。
<style>
text { font-family: 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', system-ui, sans-serif; }
</style>
フォールバック順:macOS(PingFang SC)→ Windows(Microsoft YaHei)→ Linux(Noto Sans CJK SC)→ システムのデフォルト。Noto Sans CJK SCは必ず残してください。そうしないと、Linuxでのサーバーサイドレンダリング時にCJK文字を含まないフォントにフォールバックします。
| 要素 | サイズ |
|---|---|
| タイトル | 16px |
| ボックスの本文テキスト | 12px |
| 補助テキスト/注釈 | 10px |
縦書きテキスト:<text writing-mode="tb">vertical text</text>
色
基本色:メインテキスト #1e293b、補助テキスト #64748b、控えめなテキスト/矢印 #94a3b8
セマンティックカラー:
| 意味 | 塗りつぶし | 線 | テキスト |
|---|---|---|---|
| 入力/主要 | #dbeafe | #3b82f6 | #1e40af |
| 処理中/進行中 | #fef3c7 | #f59e0b | #b45309 |
| データ/出力 | #d1fae5 | #22c55e | #166534 |
| AI/分析 | #f3e8ff | #a855f7 | #6b21a8 |
| 機密/警告 | #fce7f3 | #ec4899 | #9d174d |
矢印の定義
単純な三角形ではなく、切り欠きのある矢印を使います。こちらのほうが見やすくなります。
<defs>
<marker id="arrow" markerWidth="8" markerHeight="8" refX="2" refY="4" orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L8,4 L0,8 L2,4 z" fill="#64748b"/>
</marker>
<marker id="arrow-blue" markerWidth="8" markerHeight="8" refX="2" refY="4" orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L8,4 L0,8 L2,4 z" fill="#3b82f6"/>
</marker>
<marker id="arrow-orange" markerWidth="8" markerHeight="8" refX="2" refY="4" orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L8,4 L0,8 L2,4 z" fill="#f59e0b"/>
</marker>
<marker id="arrow-green" markerWidth="8" markerHeight="8" refX="2" refY="4" orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L8,4 L0,8 L2,4 z" fill="#22c55e"/>
</marker>
<marker id="arrow-purple" markerWidth="8" markerHeight="8" refX="2" refY="4" orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L8,4 L0,8 L2,4 z" fill="#a855f7"/>
</marker>
<marker id="arrow-red" markerWidth="8" markerHeight="8" refX="2" refY="4" orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L8,4 L0,8 L2,4 z" fill="#ef4444"/>
</marker>
</defs>
矢印の色の参照:
| ID | 色 | 用途 |
|---|---|---|
arrow | #64748b | デフォルト/中立的な接続 |
arrow-blue | #3b82f6 | 入力/主要なフロー |
arrow-orange | #f59e0b | 処理中/進行中 |
arrow-green | #22c55e | データ/出力/成功 |
arrow-purple | #a855f7 | AI/分析/特殊 |
arrow-red | #ef4444 | 警告/危険な操作 |
主なパラメーター:
orient="auto"は、パスの方向に合わせて矢印の向きを回転させますmarkerUnits="userSpaceOnUse"は明示的に宣言する必要があります。宣言しない場合、デフォルトのstrokeWidthによって矢印のサイズが線の太さに応じて拡大縮小されます(stroke-width=2 では矢印が2倍のサイズになり、意図した余白を大きく超えてしまいます)refX="2"は、線の終点を矢印の後端の切り欠きの中心に合わせ、自然なつなぎ目にしますrefY="4"は、矢印を垂直方向の中央に合わせます(矢印の高さは8、中央は4です)- 矢印のパス
M0,0 L8,4 L0,8 L2,4 zは、先端が x=8 の切り欠き形状を作ります - 先端は線の終点から6px(8-2=6)伸びるため、終点は
target edge - 11として計算します
太い線の矢印:stroke-width > 1.5 の場合(太い破線など)、8×8の矢印は小さすぎます。比例して大きなマーカーを定義します。
<marker id="arrow-red-lg" markerWidth="12" markerHeight="12" refX="3" refY="6"
orient="auto" markerUnits="userSpaceOnUse">
<path d="M0,0 L12,6 L0,12 L3,6 z" fill="#ef4444"/>
</marker>
| 線の stroke-width | マーカーサイズ | refX | 先端の延長 | 終点の計算式 |
|---|---|---|---|---|
| ≤ 1.5 | 8×8 | 2 | 6px | target edge - 11 |
| 1.5 ~ 2.5 | 12×12 | 3 | 9px | target edge - 14 |
| > 2.5 | 16×16 | 4 | 12px | target edge - 17 |
XML の特殊文字(リスクが高いため、必ず確認してください)
SVG は XML なので、テキスト内の特殊文字をエスケープする必要があります。エスケープしないと、SVG 全体が正しくレンダリングされません。
| 文字 | エスケープ | 例 |
|---|---|---|
& | & | Validate & Sanitize |
< | < | x < 10 |
> | > | x > 0 |
" | " | 属性内 |
' | ' | 属性内 |
<text>Load & Save</text>
<text>Load & Save</text>
SVG をプログラムで生成する際のエスケープ
Python/JS から SVG を生成する場合、外部ソース(CSV、データベース、API)由来のテキストは、SVG に連結する前にエスケープする必要があります。
def svg_escape(text):
return str(text).replace('&','&').replace('<','<').replace('>','>').replace('"','"')
# ❌ Splicing external data directly ("Research&Development" → XML parse failure, image won't render)
svg += f'<text>{team_name}</text>'
# ✅ Escape first
svg += f'<text>{svg_escape(team_name)}</text>'
リスクの高いデータソース:チーム名(& を含む)、要件の説明(<> を含む)、ユーザー入力、ファイル名
トラブルシューティング
| 問題 | 確認すること |
|---|---|
| 要素が重なっている | テキストと線の間隔が10px以上あるか。迂回パスが境界をまたいでいないか |
| 矢印が見えない | ブロック間隔が25px未満になっていないか。間隔を広げてください |
| ラベルが中央からずれている | text-anchor="middle" と、x が間隔の中央になっていることを確認してください |
| 矢印が逆方向を向いている | 最後のパスセグメントの方向(x/y が増加しているか減少しているか)を確認してください |
| XML の解析エラー | テキスト内の & < > がエスケープされているか確認してください |
| コンテンツの下部が切れている | viewBox の高さが小さすぎます。最下部の要素の下端 + 25px と等しくする必要があります |
| タイトル追加後、破線のグループボックスが中央からずれている | 垂直方向の中央揃えでは「タイトル + コンテンツ」の合計の高さを使う必要があります。「破線のグループボックス」を参照してください |
| 全体的に余白が多すぎる | ボックスの間隔が30pxを超えていないか、viewBox の余白が25pxを超えていないか確認してください |
検証チェックリスト
- 要素(テキスト、ボックス、線)が重なっていない
- テキストの右端が隣の要素に食い込んでいない(文字幅から推定)
- 曲線のラベルと曲線上の最も近い点との間隔が15px以上ある
- 両端の矢印に同じ余白(5px)があり、表示される線分が6px以上ある
- マーカーで
markerUnits="userSpaceOnUse"が宣言されている - 太い線(stroke-width > 1.5)では拡大したマーカーを使用している
- コネクターにはC/Q曲線を使用し、直角は使わない
- ラベルが中央揃えになっている(
text-anchor="middle") - 回避経路が障害物の外側を通っている
- ブロック間隔が25px以上ある(25~30pxを推奨。「ブロック間隔」を参照)
- タイトルが中央揃えで、ボックスがほぼ同じサイズで横一列に並んでいる
-
width属性があり、viewBoxがコンテンツに合っている - ボックスの高さが十分にある(1行の場合はフォントサイズの3倍以上)
- viewBoxの上部と下部の余白がほぼ同じ(タイトル上端から測って20~25px)
- viewBoxの左右の余白が対称になっている(そうでない場合は
<g transform="translate(dx,0)">を使って移動する) - 特殊文字がエスケープされている(
&→&、<→<) - すべての要素が表示範囲のviewBox内に収まっている(下端 = 最も低い要素の下端 + 25px)
- すべてのコネクターの意味が明確である(ラベルがある、または文脈から接続元と接続先を推測できる)
- 破線のグループ化ボックスのスタイルに一貫性がある(dasharray、角の丸み、塗りつぶし、余白、タイトルのフォントサイズ)
- 大きな空白領域がない(間隔は30px以内で、viewBoxがコンテンツに沿っている)
編集ワークフロー
1. 収集:手を加える前に変更内容をすべて把握する
SVGの変更依頼を受けたときは、すぐに編集を始めないでください。まず、次のように判断します。
- ユーザーからの変更が1つの場合 → 変更内容をまとめて把握するため、「ほかに調整したい箇所はありますか?」と返信します
- ユーザーからの変更が複数の場合 → 実行に進み、すべての変更を一度に適用します
目的は、1つずつ調整するたびにSVG全体を再出力するようなやり取りを減らすことです。
2. 実行:すべてを一度に適用し、変更一覧を示す
すべての編集が完了したら、まず変更一覧を出力し、その後に最終的なSVGを示します。
Change list:
1. Title spacing 20px → 30px
2. Box A fill #dbeafe → #f3e8ff
3. Connector L1 path adjusted (routes around the new box)
個々の編集後に図を表示しないでください。ユーザーが必要としているのは最終結果だけです。
3. レイアウトの調整:意図を把握し、関連要素も調整する
ユーザーから「ボックスAを右に20px移動して」と言われたとき、機械的にボックスAのxだけを変更しないでください。次の関連要素も調整します。
- ボックスAにつながる、またはボックスAから伸びるすべての矢印のパス
- ボックスAが並ぶ行のほかのボックスとの位置合わせ
- ボックスAのテキストラベルの位置
- ボックスAを囲む外側のボックス/背景のサイズ
間隔や配置に関する依頼(「もっと詰めて」「左揃えにして」「中央に配置して」)の場合は、全体的な意図を読み取り、関連要素を一度に調整して、ユーザーがピクセル単位で何度もやり取りしなくて済むようにします。