Dynamization Core(日本語)
これは
SKILL.mdの日本語版です。英語の正典はリポジトリ直下のSKILL.mdにあります。 ランタイムアダプタ(css/waapi/luau/porting)とspring.mdは英語のみで、references/にあります。
モーションは時間の言語だ。そのものがどこから来て、どこへ行き、いま触れる状態なのか。 輝度は空間の言語だ。何が手前にあり、何が生きていて、いまどこを見るべきなのか。
片方だけ使っても仕事は半分しか終わらない。「持ち上がる」とは 4px 上へ動かすことではない。 変位 + より大きく柔らかいシャドウ + 明るくなるサーフェス、これが同時に起きることだ。 そこまでやって初めて、脳は あれは自分に近づいてきた と読む。
「硬い」「のっぺりしている」と感じるインターフェースが、洗練されないカーブのせいで そうなっていることはまずない。物理的な直感に反しているか、3 つ動かすべきところで 1 つしか動かしていないかのどちらかだ。
このパックはどの API も所有しない。 以下の判断はすべて、人間の目で検証できる数値として 書かれている——秒単位の時間、ピクセル単位の距離、減衰比、輝度のステップ。ランタイムは §2 で 一度選んだら、あとは考えなくていい細部にすぎない。
0. Language
references/ 配下のファイルはすべて英語だ。判断を扱う章(このファイル、feel、contrast、
recipes、pitfalls、errata)の全訳は i18n/<locale>/ にある。
| Locale | Path |
|---|---|
| 繁體中文 | i18n/zh-TW/ |
| 日本語 | i18n/ja/ |
| 한국어 | i18n/ko/ |
| Español | i18n/es/ |
ユーザーにそれらの言語で回答しているなら、英語版ではなくその言語のファイルを読むこと。
アダプタ(references/adapters/)は意図的に英語のみとしている——ほぼコードと API 識別子であり、
翻訳はノイズと版ずれしか生まない。
1. 仕様の語彙
このパックのすべては 6 つの用語で書かれている。一度覚えればいい。移植されるのはこれらだ。
| Term | 意味 | 書き方 |
|---|---|---|
| dur | どれだけの長さか、秒単位 | 0.25s |
| curve | out(速く始まり収束)、in(遅く始まり加速)、inout、linear |
out |
| spring(Dv, b) | 視覚的持続時間 Dv(秒)とバウンス b(0–1)で表すスプリング |
spring(0.3, 0.15) |
| travel | 変位。そのものが実際にいた位置からの距離、px 単位 | y −4px |
| lumin | 輝度のステップ。サーフェス値またはシャドウ段階で表す | surface +1 tier |
| stagger | 兄弟要素どうしの間隔、秒単位 | 0.04s |
要となるのは spring(Dv, b) だ。Dv は動きがどれだけ長く見えるかであり、収束の尾は含まない。
だからこそスプリングとトゥイーンを同じ土俵で並べられる。b = 0 はオーバーシュートなし、
b = 1 は極端に弾む。デザインの会話でスプリングを stiffness / damping で指定してはいけない。
誰もその絵を思い描けない。変換は境界で行う → references/spring.md。
2. ランタイムを選び、あとは口を出さない
自分がいるランタイムのアダプタを読む。読むのは 1 つ。全部ではない。
| Runtime | Adapter | Tier |
|---|---|---|
CSS のみ — transition、keyframes、linear() イージング、view transitions |
references/adapters/css.md |
3 |
Web Animations API — element.animate()、ScrollTimeline |
references/adapters/waapi.md |
2 |
Luau / Roblox — TweenService、TweenInfo、RunService スプリング |
references/adapters/luau.md |
2–1 |
| その他すべて — ゲームエンジン、ネイティブツールキット、アニメーションライブラリ | references/adapters/porting.md |
— |
Tier は、構文だけでなく設計そのものを変える唯一のランタイム特性だ。
| Tier | ランタイムができること | 設計への帰結 |
|---|---|---|
| 1 | アニメーションに割り込み、速度を割り込みをまたいで引き継げる | このパックの内容はすべて書かれたとおりに機能する |
| 2 | 割り込めるが、静止状態から再スタートする(速度は失われる) | 反転を短くする。再スタートが引っかかりとして見えないよう b ≤ 0.15 を選ぶ |
| 3 | 最後まで走り切るか、割り込み時にスナップするだけ | 再トリガーされ得るものは dur ≤ 0.2s に抑える。スプリングはサンプリングしたカーブで擬似的に作る |
たいていのランタイムは既定では Tier 2 で、スプリングを自前で積分して初めて Tier 1 になる。 どちらか、そして必要ならどう 1 段上げるかは、各ランタイムのアダプタに書いてある。
そもそもライブラリやスプリングが要るのかを問え。 要素 1 つ、状態 1 つ、再トリガーなしなら、 素のトゥイーンで十分だ。スプリングが複雑さに見合うのは、割り込み可能性、速度の引き継ぎ、 ジェスチャーの引き継ぎがあるときだけ。どれも使わないなら、その代金を払う必要はない。
3. 5 つの黄金律
アニメーションを書く前に、5 つすべてをクリアすること。1 つでも破れば、多くの人が言葉にできない かたちで結果がおかしく感じられる。
1. 位置とサイズはスプリング、不透明度と色はトゥイーン
これは好みの問題ではないし、特定ライブラリの主張でもない。脳が見ているものをどう分類するかから 自然に導かれる帰結だ。
| 何をアニメーションさせるか | 使うもの |
|---|---|
位置、回転、スキュー — x y rotate とその仲間 |
spring(0.28, 0.2) — わずかなオーバーシュート |
| スケール系 | spring(0.27, 0) — オーバーシュートは絶対なし |
| 不透明度、色、ブラー、その他すべて | トゥイーン、dur 0.3、curve out |
| キーフレームが 3 つ以上 | トゥイーン、dur 0.8、curve inout |
理由。空間を占めるもの(位置、サイズ)を脳はオブジェクトとして読み、オブジェクトには質量と 慣性がある。不透明度と色はオブジェクトではない——見えるかどうかでしかない——ので、 そこにスプリングを当てるとちらつきとして読まれる。
系として:スケールを弾ませてはいけない。 弾む拡大は、ガラスにぶつかった感触になる。
この 4 行はキャリブレーション済みのセットだ。何を使うか分からないときは、そのまま使うこと。
2. アニメーションは割り込み可能であること、そして割り込みをまたいで速度を引き継ぐこと
いちばん重要で、いちばん見落とされる規則。アニメーションの途中で気が変わるのは、人間として 普通の振る舞いだ。
- 使えるならスプリングを使う。本物のスプリング積分器は現在の速度を持ち越すので、反転しても 急停止しない。弾み具合ではなくこれが、スプリングがトゥイーンに勝る本当の理由だ。
- Tier 2/3 のランタイムでは、最低限、現在の値を読み取ってそこからアニメーションさせる。 名目上の開始値からではない。再トリガーのたびに開始位置へ戻るのが、あの典型的なガタつきだ。
- キャンセルできないタイマーでアニメーションを連鎖させてはいけない。まとめてキャンセルできる シーケンス、または親子のオーケストレーションを使う。
- 割り込まれると終了状態へスナップする「トランジション」機構(組み込みのページ遷移 API の多くが そうだ)は、ユーザーが素早く再トリガーできるものには使えない。
3. 出現と退出は対称ではない
去っていくものを待たされる人がいてはいけない。
enter: opacity 0→1, y +8→0 dur 0.25 curve out
exit: opacity 1→0, y 0→+4 dur 0.15 curve in
退出は出現のおおよそ 0.5–0.7× の時間で、より短い距離を走る。去る要素が経路を最後まで たどる必要はない。目に必要なのは「出ていった」と分かることだけだ。
4. タイミングの段階:仕事が違えば予算も違う
| Tier | dur | どこで | Curve |
|---|---|---|---|
| 即時フィードバック | 0.1–0.15s |
押下スケール、チェックボックス、フォーカスリング | out または spring(0.15, 0) |
| マイクロインタラクション | 0.15–0.25s |
ホバー、ツールチップ、ボタンの色 | out |
| コンポーネント遷移 | 0.25–0.4s |
ドロップダウン、モーダル、アコーディオン、リフロー | spring(0.3, 0.15) |
| ページ / ナラティブ | 0.4–0.8s |
ルート遷移、ヒーロー、マルチキーフレーム | spring(0.5, 0.1) + stagger |
1s 超 |
ほぼ確実に間違い | ローディング、アンビエント、スクロール連動のみ | — |
ホバーのアニメーションは 0.2s を超えてはならない——カーソルはもう去っているかもしれない。 距離が長ければ多少長くしてもいいが、比例させてはいけない。距離が倍でも、増やせる時間は おおよそ 20–30% であって 100% ではない。
完全な理由づけ、スプリングパラメータの人間的な意味、オーケストレーションのリズム、 アンチパターン →
references/feel.md
5. 1 つのイベントは、複数のプロパティを同じ方向へ動かすべき
単一のプロパティが運べる情報は少なすぎる。複数のプロパティが一緒に動いてはじめて、脳はそれを 1 つの物理的イベントとして読む。
| 表現したいこと | 最低限これだけ変える |
|---|---|
| 持ち上がる / 近づく(カードのホバー) | y を上げる + シャドウを大きく柔らかく + サーフェスを明るく |
| 押される / 沈む | スケールを縮める + シャドウを引き締める + インナーシャドウ + 暗く |
| つかまれた(ドラッグ中) | スケールを拡大 + 広いシャドウ + 重なり順を上げる |
| フォーカス(モーダルを開く) | コンテンツが入ってくる + 背景を暗くする(スクリムが先に着地すること) |
| 無効 | 専用の低コントラスト色トークン(50% 不透明度ではない) |
輝度は状態のシグナルであり、変位はプロセスだ。だから輝度は動きより速く変化する
(およそ 0.12–0.15s 対 0.2–0.35s)。
ダークテーマではシャドウがほとんど見えないので、エレベーションは代わりに明るいサーフェスで 表現するしかない。テーマの切り替えはパレットではなく、機構そのものを差し替える行為だ。
画面にはもう 1 つ、ときどき第三のものが乗る——テクスチャ、つまりハッチング、グレイン、
反復する罫だ。これはチャネルではないし、仕様の用語でもない。オブジェクトが載っている地を
補強する lumin の修飾子であり、自分のはしごの最小の輝度ステップより静かでなければならない。
さもなければ、素材ではなくノイズとして読まれる。テクスチャは常にテキストに負けもする。本文の下に
ハッチングを敷くことはないし、文字のある領域では、テクスチャが目の最初に届くものであってはならない。
補強とアクセントに限ること → contrast.md §8。
光学モデル、ライト/ダークのトークンセット、各輝度プロパティをアニメーションさせるコスト、 アクセシビリティの下限 →
references/contrast.md
4. ルーティング表
目の前の仕事に対応するファイルを読む。全部読んではいけない。
| いまやっていること | 読むもの |
|---|---|
| 「自然」とは何かを理解する/感触が決まらない/「硬い」と言われた | references/feel.md ← 時間軸 |
| エレベーション、シャドウ、ダークモード、フォーカス、スクリム、コントラスト | references/contrast.md ← 空間軸 |
spring(Dv, b) をランタイムが欲しがる数値に変換する |
references/spring.md |
| 出来上がった効果をたたき台にしたい | references/recipes.md |
| CSS / WAAPI / Luau で実際の呼び出しを書く | references/adapters/<runtime>.md |
| 自分のランタイムのアダプタがここにない | references/adapters/porting.md |
| 何も動かない/カクつく/exit が発火しない/反転がガタつく | references/pitfalls.md |
| どこも壊れて見えず、完了だと言おうとしている | references/errata.md ← 出荷前に読むこと |
英語以外のロケールでは、feel、contrast、recipes、pitfalls、errata を
i18n/<locale>/ に読み替える。
5. アクセシビリティは任意ではない
大きな要素を動かす、あるいはスケールさせるものはすべて、reduced motion の設定を尊重しなければ ならない。どのプラットフォームにも存在し、名称は各ランタイムのアダプタに書いてある。
正しい振る舞いは「アニメーションを切る」ことではない。変位とスケールを無効にし、不透明度と色は 残すことだ。ユーザーは画面が変わったことをやはり学べる。スライドの代わりにクロスフェードする だけだ。パララックス、自動再生の動画、無限ループには、常にその上で明示的な分岐が要る。
6. パフォーマンスのレッドライン
普遍の法則:コンポジットは安く、ペイントは高く、レイアウトは破滅的だ。 DOM を持たないものも 含め、どのランタイムにもこの 3 段階の何らかの版がある。
- ✅ 常に安全:transform(translate / scale / rotate)と opacity — 何もリフローさせない
- ⚠️ ペイント(計測せよ):シャドウ、角丸、背景色、ブラー — 小さな要素なら問題ないが、 大きな要素や長いリストでは危険
- ❌ レイアウト(避けよ):width、height、top、left、margin、padding、ボーダー幅 — これらをアニメーションさせると、毎フレーム周囲すべてのレイアウトを解き直すことになる
高コストなプロパティに対する定石の逃げ道は、そのプロパティ自体をアニメーションさせるのではなく
両方の状態をあらかじめ描画しておき、opacity をクロスフェードすることだ。この手は
contrast.md §6 にシャドウの例として出てくるが、⚠️ の行のほぼすべてに一般化できる。
7. 数値の出どころ
このパックのパラメータ表はキャリブレーション済みのセットであり、広く使われているアニメーション 実装が出荷している既定値、およびそれらが調整の根拠にした知覚研究と突き合わせてある。ここで 素の数値として書いてあるのは、まさにこのパックを使うのにベンダーのドキュメントを取りに行く 必要がないようにするためであり、ライブラリが API を変えてもここが腐らないようにするためだ。
このパックとランタイム自身のドキュメントが API の挙動について食い違うなら、ランタイムの ドキュメントが勝つ——自分自身の振る舞いを記述しているのだから。どう感じるべきかについて 食い違うなら、このパックを優先し、そのうえで自分の目で確かめること。0.3s のスプリングは オブジェクトとして読めるか読めないかのどちらかで、それは引用を要する意見の問題ではない。