Motion match
當使用者指出某個物體在移動,並希望我們的版本以同樣方式移動,或者需要證明它確實如此時,使用此技能。最終產出的是程式碼加上數字與報表,而非「看起來差不多」。
權利優先
在擷取任何內容之前,先決定參考素材的擁有權,並在你的第一則訊息中明確說明。
| 參考素材 | 允許的行為 |
|---|---|
| 我們自己的作品,或使用者擁有或已取得授權的素材 | 任何保真度,包含像素層級 |
| 任何其他人的網站或影片 | 僅量測時序、緩動曲線、順序與距離,以書面規格記錄,並使用我們自己的設計來建構 |
對於他人的作品:
- 絕不複製他們的程式碼、著色器、素材、字型、品牌、版面或文案。絕不將真實產品重新製作為我們的版本。
- 無論請求的措辭如何,像素級精確比對都不在選項之內。應提供運動層級比對並說明原因:「我可以比對其移動方式並套用您的設計。複製他們的外觀會直接取用他們的設計成果,所以我不會這麼做。」
- 登入牆、付費牆、機器人驗證與 DRM 保護應保持關閉。尊重網站的條款,僅擷取一般訪客能看到的內容。當無法到達頁面時,請要求提供螢幕錄影。絕不下載他人的影片。
- 原始擷取檔案應存放在被 Git 忽略的本地資料夾中。它們絕不被提交、發布或用於交付物,並在使用者決定時刪除。只有書面數字會被保留。告知使用者這些檔案的位置。
如果使用者聲稱擁有某個參考素材,且沒有證據與此矛盾,則相信他們的說法,並在規格中記錄下來。「把它做得和那家公司的網站一模一樣」並不構成授權。當所有權不明確時,使用 --rights third-party。
保真度
在你的第一則訊息中說明保真度等級;它決定了你將驗證哪些項目。
| 等級 | 必須匹配 | 可能不同 |
|---|---|---|
| 運動(預設) | 觸發時機、順序、交錯延遲、每一步的時序(80 毫秒以內)、緩動曲線、方向和距離 | 顏色、字型、圖片、版面、品牌 |
| 像素(僅限自有或已授權素材) | 上述所有項目,加上字型、大小、顏色、間距和素材;平均誤差最多 2% | 使用者未要求更改的任何項目 |
| 混合 | 匹配的部分(採用上述任一層級) | 新增的部分,但不得破壞已匹配的動畫 |
僅匹配使用者指定的內容:某個區塊、某個元件,或某個時間範圍。
方法
在 output/motion-match/<name>/ 或其他 Git 忽略的資料夾中工作。保留每一輪的結果。需要 --playwright 和 --chrome 參數,或設定 PLAYWRIGHT_CORE 和 CHROME_PATH 環境變數。需要 Node 22、一個現有的瀏覽器驅動程式和一個現有的瀏覽器;處理影片時需要 ffmpeg。不自動安裝任何東西。
-
界定範圍。 撰寫目標、專案中的目的地、權利歸屬與保真度。
-
擷取參考素材:使用
scripts/capture.mjs,或對已提供的影片使用scripts/frames.mjs。根據你決定的權利給予參數:node <skill>/scripts/capture.mjs --url <頁面網址> --out <目錄>/ref --rights third-party \ --selector .hero --track ".title, .cta" --duration 2000 -
閱讀每一張報表。 執行
scripts/sheet.mjs filmstrip,然後打開每一張報表。緩動曲線存在於中間的影格中。 -
撰寫規格。 執行
scripts/spec.mjs draft:每個元素每個屬性一行。?表示你尚未完成影格判讀,且檢查功能會拒絕執行,直到每個?都被替換為正確值。 -
建構:在專案自己的技術棧中,使用自己的設計(若參考素材為第三方素材)進行實作。
-
以同樣方式錄製我們的版本。 重複使用參考素材的指令,僅更改
--url、--out和--rights參數。不同的設定會導致你的測量偏差,且compare.mjs會因此失敗。 -
比對。 依序執行
scripts/spec.mjs check、scripts/compare.mjs和scripts/sheet.mjs compare。閱讀每一張產出的報表。 -
根據數字所指出的最小問題進行修改,每輪僅修改一個原因,然後返回步驟 6。
-
若經過 5 輪後仍有任何一行失敗,則停止,並回報其數字與原因。保持閾值不變。
-
撰寫報告,使訊息能獨立陳述:包含權利與保真度;哪些部分被匹配、哪些被新增;產出的檔案與如何觸發動畫;最後一輪的比對表格;報表的路徑;每個殘留誤差的數值與原因;以及任何原始第三方擷取檔案的位置。
失敗範例
第一輪中,三張卡片中的一張失敗:
.card-1 opacity start +300 ms end +300 ms easing RMSE 0.0003 FAIL
.card-2 opacity start +300 ms end +300 ms easing RMSE 0.0055 FAIL
gaps 116.7 against 116.7 pass
每一行都有相同的延遲,且曲線和間距都正確,因此唯一的原因就是基底延遲。修改這一個數字並重新錄製。對齊影格會讓這一行通過,但卻會交付一個延遲 300 毫秒的動畫,這就是為什麼 compare.mjs 拒絕使用 --auto-align 參數來對齊兩次擷取。
常見陷阱
- 兩側的視口或裁切區域不同:在修改程式碼之前先修正擷取設定。
- 僅根據第一和最後一幀判斷:必須閱讀中間的影格。
- 字型:替代字型會改變每個影格的像素。在運動保真度層級,請閱讀時序相關的數值欄位,並忽略文字像素。
- 頁面在冷啟動時已經處於忙碌狀態:在兩側使用相同的
--wait-before參數。 - 滾動驅動的動畫會跟隨滾動位置,而非時間。在兩側使用相同的
--scroll-steps和--scroll-ms參數,並根據scrollY進行比對。 - 彈簧動畫:
easing.mjs會回報 overshoot、擬合的 stiffness 與 damping 值。根據 overshoot 與 settle time 進行調整。 - 螢幕錄製會包含游標、瀏覽器 chrome 以及壓縮噪點。將其裁切掉並略微提高
--activity-threshold。 - Canvas 內容:使用虛擬時鐘和兩側相同的
--seed參數。在真實時鐘上顯示隨機內容時,量測的是機器本身的效能。 - CSS 動畫會在
timing.easing中報告linear。真正的緩動曲線存在於每個 keyframe 中。
界線
使用 orbyn-ui-design 來決定產品應有的動畫風格,使用 technical-illustration 進行錄影,並使用 product-illustration 製作模擬 UI。影片遵循 僅限程式碼規則:研究參考素材的技術,但絕不複製其影格。
需要時再閱讀
- 關於擷取配方、觸發條件與輸出檔案,請閱讀 capture。
- 關於規格格式與如何判讀影格,請閱讀 analysis。
- 關於緩動函數、彈簧與建構模式,請閱讀 implementation。 -關於通過標準與每個失敗的含義,請閱讀 verify。