# zh-TW

> Dynamization Core（繁體中文）

- Skill: `chanlik1208-dev/zh-tw` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add chanlik1208-dev/zh-tw`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chanlik1208-dev/zh-tw/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: chanLik1208-dev (https://skillmd.com/u/chanlik1208-dev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chanlik1208-dev/zh-tw

---

# Dynamization Core（繁體中文）

> 這是 `SKILL.md` 的繁體中文版。英文正典在 repo 根目錄的 `SKILL.md`。
> runtime adapter（`css` / `waapi` / `luau` / `porting`）與 `spring.md` 只有英文版，在 `references/`。

> 動態是**時間**的語言：東西從哪裡來、往哪裡去、現在能不能碰它。
> 亮度是**空間**的語言：什麼在上面、什麼是活的、現在該看哪裡。
>
> 兩者分開用，各自只做完一半的事。「浮起來」不是把東西往上移 4px，而是
> **位移 ＋ 更大更柔的陰影 ＋ 更亮的表面，三件事同時發生。** 這樣大腦才會讀成
> *那個東西朝我靠近了*。
>
> 感覺「生硬」或「沒層次」的介面，幾乎從來不是敗在曲線不夠漂亮。它們是違反了物理直覺，
> 或是該動三個屬性的時候只動了一個。

**這套語言包不擁有任何 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. 規格詞彙

這套語言包裡的一切，都用六個詞寫成。學一次就好；能被移植的就是這些。

| 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` 是這段運動**看起來**花了多久，不含收尾的餘震——
正因為如此，彈簧和 tween 才能被放在一起比較。`b = 0` 是完全不過衝；`b = 1` 是彈到誇張。
在設計討論裡永遠不要用剛性／阻尼去描述一個彈簧；沒有人腦中浮得出那個畫面。
要換算就在邊界上換 →
`references/spring.md`。

## 2. 挑一個執行環境，然後別擋它的路

去讀你所在執行環境的轉接層。**讀一個就好，不要全部讀。**

| 執行環境 | 轉接層 | 層級 |
|---|---|---|
| 純 CSS——transitions、keyframes、`linear()` easing、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` | — |

**層級**是執行環境裡唯一會改變你*設計*、而不只是改變語法的東西：

| 層級 | 這個執行環境做得到 | 對你的設計代表什麼 |
|---|---|---|
| **1** | 中斷動畫，並把**速度**帶過中斷點 | 這套語言包裡寫的全部照用 |
| **2** | 可以中斷，但會從靜止重新開始（速度歸零） | 縮短反向動作；優先用 `b ≤ 0.15`，讓重啟不會被看成一頓 |
| **3** | 只能跑完，或中斷時直接跳位 | 使用者能重複觸發的東西一律 `dur ≤ 0.2s`；用取樣曲線假造彈簧 |

多數執行環境預設是第 2 層，只有你自己手刻彈簧積分器時才會升到第 1 層。
你那個環境的轉接層會告訴你是哪一層，以及互動真的需要時該怎麼往上爬一層。

**先問自己到底需不需要函式庫或彈簧。** 只有一個元素、一個狀態、不會重複觸發的話，
普通 tween 就夠了。彈簧的複雜度是靠可中斷、速度接手、手勢接手換來的。
這三樣你一樣都沒用到，就別付那個代價。

## 3. 五條金律

寫任何動畫之前先把這五條過一遍。違反其中一條，成品就會*怪怪的*，而且別人通常說不出哪裡怪。

### 1. 位置和尺寸用彈簧，不透明度和顏色用 tween

這不是品味問題，也不是某個函式庫的一家之言——它是從大腦怎麼分類眼前所見推導出來的。

| 在動的是什麼 | 用什麼 |
|---|---|
| 位置、旋轉、傾斜——`x` `y` `rotate` 那一家子 | `spring(0.28, 0.2)`——輕微過衝 |
| scale 家族 | `spring(0.27, 0)`——**永遠不過衝** |
| 不透明度、顏色、模糊，以及其他所有東西 | tween，`dur 0.3`，curve `out` |
| 三個以上的 keyframe | tween，`dur 0.8`，curve `inout` |

原因：會佔據空間的東西（位置、尺寸）被大腦讀成**物體**，而物體有質量、有慣性。
不透明度和顏色不是物體——它們只代表*你看不看得見它*——所以在那裡用彈簧會被讀成閃爍。

**推論：scale 永遠不要彈。** 會彈的放大讀起來像撞到玻璃。

那四列是一組校準過的數值。不知道該用什麼的時候，原封不動照用。

### 2. 動畫必須可中斷，而且最好能把速度帶過中斷點

最重要的一條，也是最常被漏掉的一條。人在動畫跑到一半改變主意，是再正常不過的行為。

- 能用彈簧就用：真正的彈簧積分器會帶著當下速度走，所以反向時不會硬生生煞停。
  **這個——而不是彈跳感——才是彈簧真正贏過 tween 的理由。**
- 在第 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. 時長分級：不同的工作有不同的預算

| 分級 | dur | 用在哪 | 曲線 |
|---|---|---|---|
| 即時回饋 | `0.1–0.15s` | 按壓縮放、核取方塊、focus ring | `out` 或 `spring(0.15, 0)` |
| 微互動 | `0.15–0.25s` | hover、tooltip、按鈕變色 | `out` |
| 元件轉場 | `0.25–0.4s` | 下拉選單、對話框、摺疊面板、重排 | `spring(0.3, 0.15)` |
| 頁面／敘事 | `0.4–0.8s` | 路由切換、主視覺、多 keyframe | `spring(0.5, 0.1)` ＋ stagger |
| 超過 `1s` | 幾乎肯定是錯的 | 只有載入、環境動態、捲動連動才適合 | — |

hover 動畫**不可以超過 0.2s**——游標可能早就移開了。
距離比較長的可以跑久一點，但**不是線性的**：距離加倍大約只換到多 20–30% 的時間，
不是多 100%。

> 完整推論、彈簧參數對應的人類語義、編排節奏、反模式 →
> `references/feel.md`

### 5. 一個事件應該讓好幾個屬性往同一個方向變

單一屬性帶的資訊太少。**大腦是靠多個屬性一起動，才把它讀成一個物理事件。**

| 要表達 | 至少要改變 |
|---|---|
| 浮起／靠近（卡片 hover） | `y` 往上 ＋ 陰影變大變柔 ＋ 表面變亮 |
| 按壓／凹陷 | scale 縮小 ＋ 陰影收緊 ＋ 內陰影 ＋ 變暗 |
| 被拿起來（拖曳中） | scale 放大 ＋ 大範圍陰影 ＋ 提升深度層序 |
| 聚焦（對話框開啟） | 內容進場 ＋ **背景變暗**（遮罩必須先到位） |
| 停用 | 專用的低對比色彩 token（**不是** 50% 不透明度） |

亮度是*狀態訊號*；位移是*過程*。所以**亮度要變得比移動快**
（大約 `0.12–0.15s` 對上 `0.2–0.35s`）。

深色主題下陰影幾乎看不見，所以層級必須改用*更亮的表面*來表達。
切換主題換掉的是機制，不只是色票。

畫面上有時候還有第三樣東西——**材質**：剖面線、顆粒、重複的紋路。它不是一個通道，
也不是規格詞彙。它是 `lumin` 的修飾語，用來強化物件所倚靠的那層底，而且必須比你階梯裡
最小的那一步亮度差還安靜，否則它讀起來會是雜訊而不是材質。它也永遠輸給文字：沒有任何
剖面線壓在連續文字底下，而且在任何有字的區域裡，材質都不能是眼睛最先碰到的東西。
只能拿來強化和點綴 → `contrast.md` §8。

> 光學模型、亮暗兩套 token、動畫化各個亮度屬性的成本、無障礙下限 →
> `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` |
| 什麼都不動、會卡頓、退場不觸發、反向會抖 | `references/pitfalls.md` |
| **看起來什麼都沒壞，而你正要說做完了** | `references/errata.md` ← **出貨前先讀** |

非英文語系：把 `feel`、`contrast`、`recipes`、`pitfalls`、`errata` 換成 `i18n/<locale>/` 底下的版本。

## 5. 無障礙不是可選項

任何**會移動或縮放大型元素**的東西，都必須尊重減少動態效果的偏好設定。
每個平台都有提供；轉接層會告訴你在你的環境裡它叫什麼。

正確的做法不是「把動畫關掉」，而是：**停掉位移和縮放，保留不透明度和顏色。**
使用者一樣知道畫面變了，只是變成淡入淡出而不是滑動。視差、自動播放的影片和無限循環，
永遠需要額外再寫一條明確的分支。

## 6. 效能紅線

通用法則：**合成很便宜，繪製很貴，版面計算是災難。** 每個執行環境都有這三層的某種版本，
連沒有 DOM 的也一樣。

- ✅ **永遠安全**：transform（translate / scale / rotate）和 opacity——它們不會引發任何重排
- ⚠️ **繪製**（要實測）：陰影、圓角、背景色、模糊——小元素沒問題，
  大元素或長列表就危險
- ❌ **版面**（避開）：width、height、top、left、margin、padding、border width——
  動這些會讓周圍所有東西的版面每一幀重算一次

昂貴屬性的標準逃生門，是**把兩個狀態都先畫好，然後交叉淡化它們的不透明度**，
而不是去動那個昂貴的屬性本身。這招在 `contrast.md` §6 裡用在陰影上，
而且幾乎可以推廣到 ⚠️ 那一列的所有東西。

## 7. 這些數字從哪來

這套語言包裡的參數表是一組校準過的數值，對照過主流動畫實作出貨時的預設值，
也對照過它們當初調校時所依據的知覺研究文獻。這裡把它們寫成白話數字，
就是為了讓**你永遠不需要為了用這套語言包而去翻某家廠商的文件**，
也讓函式庫改 API 的時候，這裡不會跟著爛掉。

當這套語言包和你執行環境自己的文件對*某個 API 做了什麼*有出入時，以執行環境的文件為準——
它描述的是它自己的行為。當兩邊對*什麼才對味*有出入時，優先照這套語言包，然後用自己的眼睛驗證：
一個 0.3s 的彈簧要嘛讀起來像個物體，要嘛不像，這件事不需要引用文獻來當意見背書。

