Motion figure(動く図)
このスキルは、動く図や入力に応答する図を作成します。3つの階層があります。Claude、Cursor、Codex、OpenClaw、Hermes、またはSKILL.mdを読み取る任意のエージェントで使用できます。
| 階層 | 作成するもの | 設置場所 |
|---|---|---|
| 1. レッスン図 | 宣言型SMILアニメーション、またはSVGを再描画するスライダーウィジェット。いずれも図フェンスからマウントされます。 | コースのレッスン |
| 2. メカニズム図 | システムの部品名を表示するHTMLパネル。ユーザーは1つのコントロールを操作し、計算された判定結果を読み取ります。 | スタンドアロンページ、README、エッセイ、レッスン外のコースサイト |
| 3. ディザフィールド | ペーパー色、アクセント色、インク色で構成され、4種類のシードモーションを持つ、WebGLによる順序ディザリングドットのバンド。 | ページのマストヘッドとセクション区切り |
第1階層はルールが最も多く、これはレッスン実行環境に厳しい制限があるためです。第2階層と第3階層にはそれぞれ専用のリファレンスファイルがあります。
使用する場面
- レッスンが時間経過に伴って変化するプロセスを説明する場合:段階を経て移動するトークン、満たされていくキュー、繰り返されるループなど。
- レッスンが、入力によって出力が変化する数式を説明する場合:学習率、温度、チャンクサイズ、バッチサイズなど。
- 著者が「この図をアニメーション化する」「スライダーを追加する」「図をインタラクティブにする」と記述した場合。
- 読者が何かを変更したときに、システムが何を行うかを示すデモ(キャッシュ、キュー、コンテキストウィンドウ、ルーターなど)が必要なページ。第2階層を使用します。
- コースカラーのゆっくり動くヘッダーが必要なページ。第3階層を使用します。
使用しない場面
- アイデアが時間軸や入力を必要としない固定構造の場合。静的なSVG図を作成します。兄弟スキルの
blueprint-figureが静的図をカバーします。 - ページが独自の状態モデルと機械構造を持つ完全な説明ページの場合。兄弟スキルの
isometric-explainerがそれをカバーします。 - パレット、フォント、散文のルールのみが必要な場合。兄弟スキルの
course-styleがそれらを保持します。このスキルは必要な部分をreferences/tokens.mdにコピーします。
方法
-
図が示す単一の変化を表す1文を書きます。2文必要なら、2つの図を作成します。
-
階層を選択します。レッスン内では第1階層を使用します。第2階層の場合は
references/mechanism-figures.mdを読み、templates/mechanism.htmlから始めます。第3階層の場合はreferences/dither-fields.mdを読み、templates/dither.jsをコピーします。以下の手順は第1階層向けです。第1階層では、変数が時間の場合はアニメーション図を、数値の場合はスライダーウィジェットを使用します。 -
ケバブケース(例:
request-pathやcontext-budget)で名前を選びます。最初にその名前がレジストリにないか検索します。後で同じ名前を登録するモジュールは、以前の図を置き換えます。 -
コードを
figures-<トピック>.jsという名前のモジュールファイルに配置します。IIFEでラップし、window.LFを読み取り、存在しない場合は早期リターンします。 -
図関数
function (host, cfg)を記述します。これは1つの.lfカードをhostに追加し、必要に応じて破棄関数を返します。 -
カードを構築します:大文字の
.lf-labelと短いヒントを持つ.lf-head、.lf-body、そしてキャプションを持つ.lf-cap。 -
SVGには
viewBox="0 0 520 H"を使用します。ほとんどのコース図ではHは200から250です。単一のバーの場合はそれより小さくて済みます。 -
<title>と<desc>を追加し、それぞれにIDを付けます。これらのIDは任意のレンダリング関数の外で一度だけ作成します。 -
アニメーション図の場合、最初にエントリーを追加し、次に1つのゆっくりしたループを追加します。
references/smil-rules.mdの各行に従います。 -
スライダーウィジェットの場合、
LF.sliderまたはLF.selectを呼び出す前にstate._renderを定義します。最後にstate._render()を一度呼び出します。 -
モジュールの最後で
LF.register({ 'your-name': fn })を呼び出します。 -
レッスンのMarkdownにフェンスを追加します。最初の行に名前を、その後にオプションのJSON設定を記述します:
```figure context-budget {"windowK": 32} ``` -
「終了前のチェック」のチェックを実行します。ライトテーマ、ダークテーマ、幅375px、動きを減らす設定がオンの状態で図を確認します。
ページが図をマウントする方法
- Markdownパーサーはフェンスを
<div class="lesson-figure" data-figure="name {json}">に変換します。 - サイトビルドは、レッスンのMarkdown内のフェンス名をスキャンします。引用された名前を含むモジュールファイルを見つけ、マニフェストを書き出します。プロバイダーのないフェンス名はビルドを停止します。
- ページは、レッスンに必要なモジュールのみを固定順序で読み込みます。新しいモジュールファイルは、リストされたファイルの後にアルファベット順で配置されます。
- マウント関数は最初の単語を名前として読み取り、残りをJSONとして解析します。JSONが不正な場合は空の
cfgが与えられます。 - 図関数がエラーを投げた場合、ランタイムはホストを空にして警告をログに記録します。レッスンの残りの部分は引き続きレンダリングされます。
- マウント後、ランタイムはタイトル、説明、
role="img"、および不足しているコントロールラベルを追加します。図がSMILアニメーションを持つ場合は一時停止ボタンを、アニメーションが一度だけ再生される場合はリプレイボタンを追加します。 - ランタイムは、図がビューポートから外れたとき、タブが非表示のとき、ユーザーが一時停止を押したときにアニメーションを一時停止します。動きを減らす設定または印刷時には、静的なフレームを表示します。
references/toolkit.mdはすべてのランタイム関数を説明し、2つの完全なモジュール例を含んでいます。
ルール
アニメーション図:
<animate>、<animateTransform>、<animateMotion>のみを使用します。図内でsetIntervalやrequestAnimationFrameは使用しないでください。- 各図のSVG要素は55個以下に抑えてください。
- エントリーは、opacity 0、scale 0.95から、opacity 1、scale 1へ変化させます。scaleを0から開始しないでください。
- エントリーは
calcMode="spline"とkeySplines="0.23 1 0.32 1"を使用します。エントリーの持続時間は0.5~0.6秒です。 - エントリーの開始を0.05~0.4秒ずつずらします。終了はエントリーより短くします。
- ループの持続時間は2.5~6秒で、
repeatCount="indefinite"を使用します。ループにfill="freeze"を設定しないでください。設定するとランタイムが一度だけ再生するためです。 - 各
keyTimesリストはvaluesと同じ数のエントリを持ちます。0で始まり1で終わり、減少することはありません。 - 各
keySplinesリストはkeyTimesよりも1つ少ないエントリを持ちます。calcMode="spline"の場合にのみ使用します。 keyPointsを持つanimateMotionはcalcMode="linear"を使用します。そのkeyPointsの数はkeyTimesの数と等しくなります。valuesは持ちません。- アニメーション化する
fillやstrokeの値にvar()を入れないでください。代わりに、目的の色を持つ2番目の要素のopacityをアニメーション化します。 - ループはopacity、transform、
stroke-dashoffset、またはパスに沿った移動のみをアニメーション化します。ランタイムはx、y、x1、y1、x2、y2、width、height、r、cx、cy、rx、ryのアニメーションを一度だけ再生します。 - ホストの
data-static-time(デフォルト1.5秒)におけるフレームは、完全で読み取り可能である必要があります。後の時点で完全な状態が表示される場合、その属性をホストに設定します。 - 要素は中心を基準にスケールします。グループの内容を(0, 0)を中心に描画し、グループを
translateで移動します。additive="sum"でスケールを追加します。
スライダーウィジェット:
- ES5のみで記述します:
var、関数式、文字列連結。アロー関数、let、const、テンプレートリテラルは使用しないでください。 - 最初の
LF.sliderまたはLF.select呼び出しの前にstate._renderを定義します。スライダーを作成する際に、レンダリング関数をラップします。 state._render内では、すべてのSVG子要素を削除し、再度追加します。ノードをその場で編集しないでください。- IDは
state._renderの外で一度だけ作成します。ランタイムは、新しいノードが持たない属性(IDを含む)を削除します。 - バーは長さまたはパス上の
stroke-dasharrayで成長させます。スケールでバーを成長させないでください。調整されたノードは中心からスケールするためです。 - 各スライダーラベルは短く、小文字で、単位を括弧内に記述します(例:
chunk size (tokens))。
両方の種類に共通:
- すべての色は、ライトテーマの値をデフォルトとするCSS変数から取得します(例:
var(--blueprint,#3553ff))。変数が機能しない場合にのみリテラルな16進数を使用します。 - メインの対象には最大1つのアクセントカラー(
--blueprint)を、もう1つの状態には--warnを使用します。残りにはインクとルールトークンを使用します。 - SVGテキストは12単位以上で、
var(--font-mono)を使用して設定します。ラベルを小さくする必要がある場合は、SVGの最小幅を500pxに設定し、横スクロールできるようにします。 - ラベルのサイズを電話で確認します。375pxの画面では、カード内の520ユニットのSVGは幅279pxで描画されます。12ユニットのラベルは約6.4pxで描画されます。
- キャプションは平易な技術英語で記述します。各色が何を意味するかを明記します。文章は25語以内に抑えます。
.lf-labelのラベルは大文字で、2~4語とします。
メカニズム図(第2階層):
- 実在の名前と実在の数値を表示します:ファイル名、キー、トークン数。
item 1や名前のないグレーのバーは避けてください。 - ユーザーに1つのコントロールを提供します:ステップ、スライダー、トグル、再生、または一部の停止。
- テキストの判定行で終了します。本文の数値から計算されたものとします。固定の結果を記述しないでください。
- 図の35%が可視になったときに一度実行し、リプレイボタンを追加します。ループはしません。
transformとopacityのみをアニメーション化し、cubic-bezier(0.23, 1, 0.32, 1)を使用します。押下は120~160ms、表示は200~300ms、折りたたみは380~500msとします。- アイテムあたり30~70msずつリストをずらします。最初の8アイテムのみに適用します。
- すべてのフレームで各ラベルを完全に表示します:省略記号なし、重なりなし、ドット上にテキストなし。テキストは11px以上、判定行は12.5px以上とします。
- 幅320pxでは、パネルを1列に積み重ね、各コントロールに40pxのタッチターゲットを与えます。
- サイト上の他のページで使用されていないメカニズムを使用し、サイトのメカニズムテーブルに追加します。
ディザフィールド(第3階層):
--bg、--blueprint、--inkから色を読み取り、data-themeが変更されたときに再描画します。- 最大で毎秒30フレームで描画し、バンドが可視の間のみ描画します。
- 動きを減らす設定では、1つの静的フレームを描画します。WebGLがない場合は、静的なハッチを表示します。
- バンドに
aria-hidden="true"をマークし、ラベルチップを除いてドット上にテキストを配置しません。
終了前のチェック
- フェンス名が登録名と完全に一致し、他のモジュールがそれを登録していない。
- モジュールに
=>、let、const、またはバックティック文字列がない。 - モジュールに
setIntervalやrequestAnimationFrameがない。 -
references/smil-rules.mdのバリデーターが、マウントされたホストに対して空のリストを返す。 - 各アニメーション図のSVG要素が55個以下である。
- すべてのループの持続時間が2.5秒から6秒の間である。
- ルール11のジオメトリ属性をアニメーション化するループがない。
- 動きを減らす設定がオンの場合、図は完全な画像を表示し、欠落している要素がない。
- ダークテーマで、すべての線とラベルが可視である。
- 幅375pxで、すべてのラベルが読みやすく、図の外に横スクロールがない。
- ウィジェットの場合、各スライダーを最小値と最大値に動かしても、
NaN、負の幅、コンソールエラーが発生しない。 - SVGに1つのタイトルと1つの説明があり、スライダー移動後もそれらのIDが変わらない。
- キャプションが図で使用されているすべての色を明記している。
- 第2階層:
references/mechanism-figures.mdの最後にあるチェックリストのすべての項目を満たす。 - 第3階層:
references/dither-fields.mdの最後にあるチェックリストのすべての項目を満たす。
ファイル
references/smil-rules.md:12のSMILルールの全文、各ルールが防ぐもの、ブラウザコンソールで実行できるバリデーター。references/toolkit.md:LF関数とマウントシーケンス。完全なスライダーウィジェット、完全なSMIL図、およびコースサイト外で使用するためのプレビューページも含まれています。references/tokens.md:ライトテーマとダークテーマのカラートークン、フォント、モーションタイミング値。references/mechanism-figures.md:第2階層。実在の名前、拒否された図、メカニズムの形状、構造、判定、モーションバジェット、チェック。references/dither-fields.md:第3階層。シェーダーの描画方法、4つのモーション、マークアップ、ルール、ディザリングされたバー、チェック。templates/mechanism.html:完全な第2階層の図。サイズコントロール付きのLRUキャッシュで、任意のブラウザで開けます。templates/dither.js:完全な第3階層のスクリプト。ロードして<div class="dither" data-seed="...">を追加します。
AI Engineering from Scratchリポジトリ内では、ランタイム用のsite/lesson-figures.jsと、さらに多くの図用のsite/figures-*.jsも参照してください。