dashmotion について
Dashmotion は、自己完結型 HTML ファイルでアニメーション技術図を作るスキルです。フロー図とアーキテクチャ図に対応し、指定された Mermaid 入力も扱えます。レイアウトやアニメーションの問題を自動検査します。
主な機能
- 01フロー図とアーキテクチャ図のモード
- 02Mermaid のフローチャートと状態図に対応
- 03破線コネクターと移動ドットのアニメーション
- 04インライン SVG の自己完結型 HTML
- 05レイアウトと図の整合性の自動検査
活用シーン
- 01処理手順や状態遷移の図示
- 02サービスやインフラのトポロジー表示
- 03対応する Mermaid 図のアニメーション化
- 04図の配置やアニメーションループの検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ csthink/ dashmotion --skill dashmotionインストール後、Claude Code で/dashmotionを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/architecture-mode.mdflow-mode.mdlayout-script.mdmermaid-input.mdresources/template-architecture.htmltemplate-flow.htmlscripts/check_diagram.pycheck_fidelity.pylayout.py詳細
Dashmotion
プロフェッショナルなアニメーション付き技術図を、自己完結型の単一HTMLファイルとして作成します。名前がその実装を表しています。stroke-dashoffsetアニメーションとanimateMotion、それだけです。出力はベクター形式で、無限にループし、サイズは数KBで、どのブラウザーでも開けます。
ステップ1 — モードを選ぶ
| ユーザーの要望 | モード | 参照先 |
|---|---|---|
| 手順、シーケンス、分岐、並列実行、状態遷移(「何が、どの順番で起きるか」) | フロー | references/flow-mode.md + resources/template-flow.html |
| コンポーネント、サービス、インフラストラクチャ、包含関係、トポロジー(「システムが何で構成されているか」) | アーキテクチャ | references/architecture-mode.md + resources/template-architecture.html |
複合的なリクエスト(「マイクロサービスと、その間を注文がどう流れるかを示して」)→ アーキテクチャモードを選びます。アニメーション付きのリクエストパスが、フローそのものです。トポロジーでは表現できない分岐ロジックがある場合に限り、別々の2つのファイルを作成します。
Mermaid入力 — リクエストにMermaidソース(```mermaidブロック、.mmdファイル、または貼り付けられたコード)が含まれている場合は、何よりも先にreferences/mermaid-input.mdも読んでください。サポート対象はflowchart/graphとstateDiagram-v2です。それ以外の図の種類はサポート対象外のため、その旨を伝えて代替案を提示してください。上記のモード選択は引き続き適用されます(Mermaidは構文であり、意味ではありません)。また、ソースに記載された方向にかかわらず、レイアウトは常に上から下へ再計算されます。
作業を始める前に、モードのリファレンスファイルを読んでください。 そこにあるレイアウト計算が、scripts/layout.py(ステップ5)で実装されています。クリーンなセマンティックグラフを作成し、スクリプトのジオメトリに色/形状/アニメーションのスタイルレイヤーを適用するため(また、フォールバックを手作業で計算するため)に参照してください。これにより、重なり、ボックスを貫通する矢印、壊れたループといったよくある問題を防げます。
ステップ2 — 2つのアニメーション規約(両モード共通)
流れる破線コネクター — stroke-dashoffset
.flow { stroke-dasharray: 5 5; animation: dashmove 0.75s linear infinite; }
@keyframes dashmove { to { stroke-dashoffset: -10; } }
- オフセットの変化量は、
stroke-dasharrayの1周期分(ここでは5+5=10)と完全に一致させてください。一致しないと、ループ時に目に見える飛びが発生します。 - 負のオフセットはパスの描画方向へ流れます → コネクターの
dは、常にソースからターゲットへ向かうように記述してください。 - 0.6〜0.9秒なら「電流」のように見えます。1.5秒より遅いと、途切れているように見えます。
移動するドット — <animateMotion>
<circle r="3.5" class="dot" fill="#34d399">
<animateMotion dur="2s" repeatCount="indefinite"
path="M400 178 L400 204 L170 204 L170 222"/>
</circle>
pathにはコネクターのdをそのまま使います。ドットは線上を正確に移動します。- 円には
cx/cyを指定しません。位置はanimateMotionが決めます。 begin="0.7s"などで開始タイミングをずらします。図1つにつき、ドットは合計3〜6個にします。方向が伝わる場所(分岐、合流、主要なリクエストパス)に配置し、すべての辺に置かないでください。- アーキテクチャモードでは、ドットは意味的に飛行中のリクエスト/メッセージです。現実的なエンドツーエンドの経路に沿ってドットを移動させてください。
ステップ3 — 共通のデザイントークン
- ページ:
#020617、40pxグリッドパターン(#0f1b33、0.5pxの線)。JetBrains Monoがローカルにインストールされていれば使用し、なければシステムの等幅フォントスタック(ui-monospace, 'SF Mono', 'Cascadia Code', Menlo, Consolas, monospace)を使用します。Webフォントの取得は行いません。ファイルは完全に自己完結しています。 - テキスト:ラベルは
#e2e8f013px/500、サブラベルは#64748b10px、凡例は11pxです。 - ノードの角は
rx="8"。START/ENDのピルはrxを高さの半分にします。 context-strokeを使用した共通の矢印マーカを1つ用意します(各線の色を継承します)。
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</marker>
- コネクターの端点は、ノードの縁から4px手前で止め、矢印が境界線を貫通しないようにします。
- すべてのコネクター
<path>には、必ずfill="none"を指定する(またはfill="none"の<g>内に配置する)必要があります。SVGのデフォルトは黒で塗りつぶされるため、これを指定しないとL字型パスが巨大な黒いポリゴンとして描画されます。 - Z順の描画順序:グリッド → コネクター → ドット → ノード。ノードが線の端を覆い、ドットはノードの上を滑るのではなく、ノードの中に「消える」ように見えます。
- ViewBox:
0 0 W H。Hは最も下にある要素の下端+50とします。負の座標は使用しません。
ステップ 4 — アクセシビリティとモーション(必須)
- すべての CSS アニメーションを
@media (prefers-reduced-motion: no-preference)で囲みます。 - SMIL はこのメディアクエリーを無視するため、低減されたモーション設定では
.dot要素を削除し、表示されている⏯一時停止トグル(animation-play-state: paused+svg.pauseAnimations())を接続するテンプレートのインラインスクリプトを残します。 - SVG に
role="img"+<title>+<desc>を付けます。
ステップ 5 — ファイルを生成する
dashmotion には決定論的なレイアウトエンジン scripts/layout.py(標準ライブラリのみ)が付属しています。モードのリファレンスに記載された座標計算(行の配置、分岐間の間隔、境界のパディング、直交するレール/レーンのルーティング)を行い、完成した HTML もレンダリングします。ジオメトリ、モードのスタイルレイヤー、作成したテキストを組み合わせるため、座標を手計算したり、35 個の rect と 38 個の path d をテンプレートに手作業で転記したりする必要はありません(どちらも時間がかかります)。決めるのは意味とテキストであり、スクリプトがファイルを書き出します。仕様の全文は references/layout-script.md を参照してください。
スクリプトのパス — python3 が使える場合は必ず使用してください:
- リクエスト、または
references/mermaid-input.mdに従った Mermaid ソースを、references/layout-script.mdのセマンティックグラフ JSON に変換します。ここが判断を行うレイヤーであり、図に必要なすべての情報を含めます。- 構造:ノード(アーキテクチャの場合は
typeとtier— グループ化されていない/単一グループのアーキテクチャではtierを省略します(エンジンが自動でレイヤーを設定します)。複数グループの場合は指定してください。layout-script.mdを参照してください。境界への所属を示すノードごとのgroup。フローのshapeはピルと判断ノードにのみ記述し、"shape": "step"は記述しないこと。ステップでは省略します)、エッジ(kind)、グループ、ジャーニー、必要に応じてlegendExtra、classDefの保持。 - テキスト:
title、subtitle、および(アーキテクチャの場合)正確に 3 枚のカードからなるsummary(アクセントは cyan/violet/rose、title、items[])。図を見る人に伝える文言は、JSON 内でここに記述します。
- 構造:ノード(アーキテクチャの場合は
- 出力フォルダーではなく、一時パスに書き込みます。例:
"$TMPDIR/dashmotion-graph.json"(または任意のmktempパス)。その後、python3 <this-skill-directory>/scripts/layout.py "$TMPDIR/dashmotion-graph.json" --render <topic>-dashmotion.htmlを実行します。セマンティック JSON はビルド中だけ使用する中間ファイルです。納品する HTML はこれに依存しないため、.htmlと同じ場所に JSON を書き込まないでください。ユーザーのフォルダーには完成した図だけを置きます。スクリプトはジオメトリを計算し、スタイルレイヤーを適用し(typeに応じたノードの塗りと線、ベースを不透明にした図形とスタイル付き rect のマスキングペア、エッジのkindに応じたflow/flow-async/flow-authコネクタークラス、ジャーニーごとのドットの色と、段階的に連鎖するbegin)、作成したテキストを挿入して、完全な自己完結型の、すぐに納品できるファイルを書き出します。"loop": trueのエッジはパスではなく、↻ labelの注釈としてレンダリングされます。 - そのファイルに対してステップ 6 を実行します。レンダラーは構造的に適切なものを生成しますが、最終判断はステップ 6 に委ね、必ず実行してください。
- 見た目については、引き続きすべての最終決定権を持ちます。文言、強調、ジャーニー、タイプを調整するには、JSON を編集して再レンダリングします(手軽で決定論的です)。ラベルや色を手作業で調整するには、生成されたファイルを直接編集します。座標を転記する作業はもう必要ありません。ジオメトリ(プラン A)と、それを囲む定型コードの生成はスクリプトが担います。
JSON を作成したうえで、HTML も手作業で書かないでください。そうすると、この方法で取り除いたはずの転記作業が再び発生します。レンダリングし、確認して、納品してください。
手計算による代替手順 — python3 が使えない場合に限る: 座標を書く前に、モードのリファレンスに従ってレイアウトを明示的に計算します。テンプレートをコピーし、SVG の内容/タイトル/ヘッダー/凡例/サマリーカードを置き換えます(CSS、⏯一時停止トグル、低減されたモーション用スクリプトはそのまま残します)。コネクターの d 値をコピーして間隔をずらしながら、3〜6 個のドットのパスを選びます。これは 2.2 より前の方法です。時間はかかりますが、Python は不要です。
ファイルはどのブラウザーでも直接開けることをユーザーに伝えてください。
GIF/MP4 へのエクスポート(依頼された場合のみ)
フレームを手作業でレンダリングしてはいけません。開いているファイルを画面収録するか(macOS ⌘⇧5)、ヘッドレスで実行します。
npx timecut <file.html> --viewport=1200,900 --duration=3 --fps=30 --output=flow.mp4 を実行し、その後 ffmpeg -i flow.mp4 flow.gif を実行します。
すべての継続時間が 3 秒で割り切れる場合、3 秒のキャプチャはシームレスにループします。GIF へのエクスポートが目的なら、0.75 秒/1.5 秒/3 秒を優先してください。
ステップ 6 — 構造のセルフチェック(提出前)
ファイルは書き終えた時点では完成ではありません。このチェックに合格して初めて完成です。--render の出力は構造的に問題がないことが保証されていますが、それでもチェックは必須です(座標が予測可能な形で失敗する手計算の代替手段に対するガードにもなります。コネクターレイヤーはテキストレイヤーよりはるかに頻繁に失敗します)。思い込まず、検証してください。
自動化された方法(python3 が使える場合は必ず使用): 書き出したファイルに対して、同梱のチェッカーを実行します —
python3 <this-skill-directory>/scripts/check_diagram.py <your-file>.html
以下の失敗の種類(重なり、ボックスを通るコネクター、破線ループの継ぎ目、範囲外、線から外れたドット、黒塗り、端点の突き抜け、宙ぶらりんの begin 参照、不正な XML)を決定論的に検出します。報告された違反をすべて修正し、「0 violations」と表示されるまで再実行してください。スクリプトが利用できる場合は、計算を手作業で追ってはいけません。独自の場当たり的な検証スクリプトを書いてはいけません。また、ブラウザーで開いたりスクリーンショットを撮ったりして検証してはいけません。スクリプトを正とし、スクリプトでは確認できない項目(ラベルの衝突、境界の正確な余白、凡例の配置)は数値を読んで確認してください。
入力が Mermaid の場合: 忠実性の再カウント(チェックリスト項目 6)も自動化します。ソースを一時 .mmd ファイルに保存し、次を実行します —
python3 <this-skill-directory>/scripts/check_fidelity.py <source>.mmd <your-file>.html
「PASS」と表示されるまで修正してください。ソースのノード/エッジ/グループのラベルがすべて一字一句そのまま含まれていることと、コネクター数がソースのエッジ数と一致することを検証します。そのため、ラベルと凡例の項目はソースの表記を厳密に維持してください。言い換えたり、2 つのソース文字列を 1 つにまとめたり、括弧を追加したりしてはいけません(凡例の項目 v2 点线橙框 は v2 点线橙框 のままにし、v2 治理骨架(点线橙框) にしてはいけません)。これは構造チェックと同じく、再現率の低い落とし穴です。「一字一句そのまま維持した」と文章で確認しても、実際の差異を見落とすことがありますが、スクリプトなら見逃しません。
文章による代替手段(python3 が使えない場合のみ): 以下の各項目を、コードをざっと見るのではなく、実際の数値を使って計算し検証してください(比較を書き出します)。違反をすべて修正し、リストに問題がなくなるまで再確認してください。
- 重なり — 同じ行にある要素の各ペアについて、
left.x + left.width + gap ≤ right.x(gap ≥ 20 flow / 40 architecture)を満たしてください。上下に積み重ねた各ペアについては、top.y + top.height + gap ≤ bottom.yを満たしてください。境界は、四辺すべてに20px以上の余白を取り、子要素を完全に内包する必要があります。2つのボックスが部分的に重なる場合は、必ず不具合です。 - ボックスを通過するコネクタ — すべてのパスをセグメントごとに確認してください。両端点の間で、パスがノードの矩形内に入ってはいけません。各水平レールについて、通過する矩形と
yを照合してください(rect.y ≤ y ≤ rect.y + heightなら衝突です)。垂直方向の下向き線についても、同様にxを確認してください。ボックスを少しずつ動かして別の箇所を壊すのではなく、レールパターンを使って経路を引き直してください。 - アニメーションのループ — アニメーション対象の各クラスについて、
|stroke-dashoffset delta|がstroke-dasharrayの周期の合計の正確な倍数である必要があります(例:5 5→ 10)。インラインでdasharrayを上書きしているコネクタも対象です(非同期の2 4のエッジを-10のキーフレームでアニメーションさせると、サイクルごとにつなぎ目ができます。そのエッジ専用のキーフレームを用意してください)。各animateMotionについて、トレースするコネクタを1つ指定してください。2つのコネクタにまたがるドットのパスは、その間のコンポーネントをまっすぐ通過するため、ホップごとに分割したドットを連結してください。すべてのbegin="X.end+…"で、参照先のidが存在することを確認してください。 - ViewBoxの範囲 — 座標に負の値を使用しないでください。すべての矩形の
x+width/y+heightと、すべてのパス座標が0 0 W Hの範囲内に収まる必要があります。Hは最も下にある要素の下端 + 20以上にしてください。凡例は最も下にある境界の下に配置してください(architecture)。 - コネクタとマークアップの整合性 — すべてのコネクタの
<path>でfill="none"が指定されている必要があります。端点は対象の枠線の手前約4pxで止め、ボックスの内側に入り込まないようにしてください。SVGコメント内で--を使用しないでください(``はコメントを早期に閉じ、余分なテキストがドキュメント内に漏れます)。 - Mermaidとの一致(Mermaid入力のみ) — 上記の
check_fidelity.pyで機械的に検証します。実行してPASSになるまで修正してください。ソースと照合して数を再確認します。ノードの矩形/ピルはソースのノードIDと一致します([*]に対してのみSTART/ENDのピルが追加されます)。コネクタのパスと↻で描画されるループは、チェーンと&を展開した後のソースのエッジと一致します。すべてのノード、エッジ、グループ、凡例のラベルが一字一句そのまま表示されている必要があります(图例サブグラフから統合した凡例項目も対象です。テキストを正確に保持してください)。python3がない場合は、手作業で数を確認してください。詳細はreferences/mermaid-input.mdを参照してください。
修正が必要な箇所が何もない状態で検証に合格した後にのみ、ファイルを納品してください。
出力仕様
自己完結型の.htmlファイルを1つ作成してください。CSSを埋め込み、SVGはインラインにし、外部アセットとJS依存関係は使用しないでください。例外として、約15行のインラインの一時停止/視覚効果を減らすスクリプトのみ使用できます。ファイルシステムから開いても正しく表示されるようにしてください。