Pryne 前端除錯手冊 是做什麼的?
針對 Pryne 的 vanilla-JS 展示建構提供症狀→初步診斷:由 window.Roll 模組核心 (design-demos/js/roll-*.js) 驅動的單一 HTML 頁面,包含 WebGL 顆粒著色器 (附 2D 備援)、一個 rAF 渲染循環、自行維護的 Lenis 平滑滾動,以及從 CDN 非同步載入作為漸進增強的 GSAP。
必要背景: superpowers:systematic-debugging 擁有通用根本原因排查規則 (未經調查不得修復)。請遵循該規則;此技能僅提供專案特定的症狀對照表與常見陷阱。
工具: 關於如何驅動瀏覽器、擷取主控台、模擬減少動畫模式以及取得追蹤記錄,請使用 pryne-browser-lab。此技能假設您已能執行這些指令。
先讀取檔案頭部註解
每一個 v4 展示 (design-demos/ 中的 v4-a 至 v4-d) 在其檔案最頂端以 HTML 註解的形式攜帶稽核歷史紀錄 — 記錄了什麼被發現損壞、什麼已修復以及原因。此慣例於 2026-07-22 在所有四個檔案中驗證通過。在重新診斷任何問題之前,請對您正在除錯的展示執行 head -30。 您會發現許多「錯誤」實際上已記錄為已修復的回歸;如果某個問題再次出現,您要尋找的是導致其回滾的原因,而非一個新的根本原因。
另外請注意建構佈局 (截至 2026-07-22):僅 v4-d-hybrid.html 使用共用的 roll-*.js 模組。v4-a/b/c 是範圍縮小的比較建構,使用各自獨立的內嵌 JS — 此對照表中針對 Roll 的檢查不適用於它們,但相同的錯誤類別仍然適用。
零主控台錯誤是默認狀態
標準是零主控台錯誤 (design-demos/DECISIONS.md 中的 CRITIQUE 評分標準要求如此)。根據專案狀態日誌,v3 已驗證為零錯誤;v4 系列則在方向決策活動 (pryne-design-direction-decision) 完成前尚未認證。任何主控台錯誤都是需要處理的缺陷,絕非可以忽略的環境雜訊。
症狀 → 初步診斷對照表
| 症狀 | 可能原因 | 區分性檢查 |
|---|---|---|
| 動畫/開發面板在其區塊被滾動至可視區域前就執行(或完成) | 可視性閘門控制回歸。v4-d 的頭部註解記錄此為最高優先級的稽核修復:功能面板「從頁面載入時即無條件觸發,並在任何人滾動到它們之前就完成解析。」開發必須以面板的 .in 類別作為閘門控制。 | 下方的實驗 1 |
| 顯現動畫裁切錯誤、跳動或從未觸發 | clip-path 被應用在 IntersectionObserver 所監聽的元素上,而非一個內層的包裝元素。概念 C 的修復(已帶入 v4-d,根據其頭部註解):clip-path 顯現效果位於內層包裝元素上,絕不在監聽的元素上。 | 檢查元素:監聽的節點與套用裁剪的節點是否為同一個? |
| 作業系統游標消失,且無自訂游標取代 | 不應再次發生 — 已於 2026-07-22 修復(經冷測試稽核查出,同日修復):每個事件處理器 (roll-cursor.js:17-20) 及其 pointermove 呼叫點 (roll-core.js:26-29) 現在都會在原有設定時期的捕捉之外,額外進行捕捉與還原 (設定 null Roll.cursorUpdate,移除 .custom-cursor);#cur/#ring 的 z-index 從 50 提高至 70,高於 #flash (60),以使高潮脈衝無法覆蓋游標。如果症狀再次出現,表示其中一個防護措施發生回歸,或有新程式碼在此合約之外隱藏了游標。 | document.body.classList.contains('custom-cursor') 對比 Roll.cursorUpdate — true/null 同時存在是故障狀態;如果兩者看起來都正常,檢查 getComputedStyle(cur).opacity,以及是否僅在高潮閃光時消失 |
| WebGL 殘影/軌跡,或顏色與頁面混合錯誤 | 缺少逐影格清除 (per-frame clear),或預乘 alpha 設定不匹配 (premultiplied-alpha mismatch)。roll-shader.js 每影格呼叫 gl.clear(gl.COLOR_BUFFER_BIT),並以 { alpha: true, premultipliedAlpha: false } 建立 context (兩者皆為稽核修復,根據 v4-d 的頭部註解)。 | 比對 roll-shader.js 與 git:git diff HEAD -- design-demos/js/roll-shader.js |
| 著色器畫布空白,完全沒有顆粒效果 | (a) 減少動畫模式 — GL 故意永不初始化 (useGL = !Roll.reduced && setupGL());(b) WebGL context 遺失 — webglcontextlost 處理器將畫布透明度設為 0 並靜默失敗;(c) 在 WebGL 有機會前就已取得 2D context (每個畫布只能有一個 context — 於 roll-shader.js 頂部有文件說明)。 | 優先檢查 Roll.reduced。針對 context 遺失,檢查處理器的可觀察效果:getComputedStyle(document.getElementById('tone')).opacity === '0'。注意:Roll.shader.useGL 是設定時的快照 (roll-shader.js:120-121) — webglcontextlost 處理器僅翻轉閉包變數 (roll-shader.js:130-132),因此 context 遺失後 Roll.shader.useGL 仍為 true;不要用它來排除 context 遺失的可能性 |
| 滾輪編排失靈,但頁面仍正常渲染與滾動 | 腳本載入順序或 window.Roll 命名空間中斷。腳本順序至關重要 — 其鏈結與檢查指令位於 pryne-frontend-architecture。每個模組都是一個 IIFE,僅透過 window.Roll 共享狀態;早期模組中發生一個錯誤就會導致其後所有模組因無法執行而停止。 | 下方的實驗 2;主控台會顯示 Roll.X is undefined,指出是哪個模組被影響而無法執行 |
| 單一使用者回報所有動畫失效,但在您的機器上正常 | 他們啟用了 prefers-reduced-motion。這是正確行為,非錯誤:roll-core.js 從媒體查詢設定 Roll.reduced,且每個模組都以此為閘門 (封面移除、面板立即完成渲染、跳過 Lenis、關閉著色器)。請勿「修復」它。 | 下方的實驗 3 |
| 觸控板/滑鼠滾輪/觸控的滾動感受不一致 | 原始滾動 Delta 值變異 — 這是自行維護 Lenis 的記錄原因 (參見 design-demos/DECISIONS.md)。Lenis 包裝了原生滾動,因此 window.scrollY 仍然有效;它僅是感受上的升級,在減少動畫模式下為 null。 | typeof Lenis (是否已載入?),然後檢查展示是否在其滾動模組中建構了它 |
| 基礎功能正常,但缺少懸停/動態/游標效果 | GSAP CDN 載入失敗或被阻擋。GSAP 從 jsdelivr 非同步載入 (固定 SRI),並僅在成功載入後透過 Roll.upgradeMotion() 將 Roll.enhanced = true。漸進增強是設計使然:基礎編排仍必須在沒有 GSAP 的情況下正常運作。如果基礎功能也同樣損壞,則此非本次原因。 | 下方的實驗 4 |
| 音訊靜默 | 靜音是默認狀態:roll-audio.js 以靜音啟動,將選擇持久化儲存在 localStorage['ch001_muted'] 中,且僅在點擊 #mute-toggle (使用者手勢,滿足自動播放政策) 後才開始播放環境背景音。所有合成邏輯都已用 try/catch 包裹且無需資產檔案。在懷疑程式碼之前,請先檢查靜音切換按鈕的狀態。 | Roll.audio.muted,以及 localStorage.getItem('ch001_muted') |
| 固定的 HUD 重疊/遮擋了頁尾 | 頁尾淡出修復的回歸:一個監聽 footer 的 IntersectionObserver 在節拍計量器和靜音按鈕上切換 .faded 類別 (roll-scroll.js)。 | 滾動到頁尾;檢查 #beatmeter 上是否出現了 .faded 類別 |
區分性實驗
在頁面主控台中或透過 evaluate_script (參見 pryne-browser-lab) 執行這些指令。每個指令能在您碰觸程式碼前回答一個問題。
1 — 面板開發是否正確地以可視性為閘門?
({ workVisible: document.getElementById('work').classList.contains('in'),
plate1: { d: Roll.featurePlate.d, done: !!Roll.featurePlate.done },
plate2: { d: Roll.featurePlate2.d, done: !!Roll.featurePlate2.done } })
在新載入後,滾動至工作區塊前:workVisible: false 且兩個 d 值應接近 0。如果 d 在上升 (或 done: true) 但 workVisible 為 false,則表示閘門控制發生回歸。
2 — Roll 核心是否完整?
({ core: !!window.Roll, reduced: Roll?.reduced, enhanced: Roll?.enhanced,
shader: !!Roll?.shader, audio: !!Roll?.audio, plates: !!Roll?.plates,
cursorUpdate: Roll?.cursorUpdate === null ? 'null' : typeof Roll?.cursorUpdate })
關於 cursorUpdate:它初始化為 null (roll-core.js:23),且在 GSAP 載入前以及非 pointer: fine 裝置上也是 null — 僅 null 本身不能證明任何事。「安全失敗」僅在 document.body.classList.contains('custom-cursor') 為 true 且 cursorUpdate 為 null 時才成立 (參見對照表中的游標行)。
任何 false/undefined 指出了未完成載入的模組 — 請檢查主控台中該模組拋出的錯誤,並檢查 HTML 中的腳本順序是否符合上述的載入順序。
3 — 「所有動畫失效」是否只是減少動畫模式?
({ mediaQuery: matchMedia('(prefers-reduced-motion: reduce)').matches, roll: Roll.reduced })
兩者皆 true → 符合設計;透過模擬減少動畫模式 (pryne-browser-lab) 重現使用者回報。mediaQuery: true 但 roll: false (或相反) → 某個模組讀取了錯誤的資訊來源。
4 — GSAP 增強層是否已載入?
({ gsapLoaded: !!window.gsap, enhanced: Roll.enhanced, reduced: Roll.reduced })
gsapLoaded: false → CDN 被阻擋或載入失敗 (檢查網路面板中對 jsdelivr 的請求;SRI 不符也會導致此情況)。gsapLoaded: true, enhanced: false, reduced: false → upgradeMotion() 未執行 — 檢查 <script> 標籤的 onload 鉤子。
耗費大量時間的常見陷阱
| 陷阱 | 故事 (一句話) | 防護措施 |
|---|---|---|
| 「驗證正常」≠ 方向正確 | v3 NIGHT DRIVE 完全建構完成,零主控台錯誤,通過驗證 — 然後被取代,因為其統一概念是錯誤的 (完整說明:pryne-failure-archaeology)。 | 不要花費打磨/除錯精力來維護一個尚未被確認是目前方向的建構。請先檢查 DECISIONS.md 和文件庫狀態。 |
| 重新診斷已記錄的修復 | 每個 v4 的頭部註解都是已找到、已修復缺陷的變更紀錄。 | 在開啟開發者工具前,請先讀取頭部註解。如果列表中的某個修復看似損壞,請尋找導致回滾的原因,而非症狀本身。 |
| 「修復」減少動畫模式 | 所有動畫關閉是針對 prefers-reduced-motion 使用者的設計行為,由一個地方 (Roll.reduced) 進行閘門控制。 | 在將零動畫回報視為缺陷前,請先執行實驗 3。 |
| 為了「測試某個東西」而取得 2D context | 一個畫布永遠只能擁有一種 context 類型;先取得 2D context 會導致該畫布從此無法使用 WebGL (於 roll-shader.js 中有文件說明)。 | 在主控台實驗中,絕對不要在 #tone 上呼叫 getContext('2d')。 |
何時不應使用此技能
- 通用除錯規則 (提出假設、最小變更、先找根本原因再修復) → superpowers:systematic-debugging。
- 如何驅動瀏覽器/進行測量 (MCP 工具結構、追蹤記錄、Lighthouse、螢幕截圖) → pryne-browser-lab。
- 判斷行為是否違反設計不變量 (減少動畫閘門控制、低語級別個性、自行維護) → pryne-frontend-architecture。
- 關於某個東西為何被建構/回滾的完整歷史 → pryne-failure-archaeology。
- 其他技術棧 (React/框架建構、非 Pryne 專案):上述對照表專屬於
window.Roll展示系列;僅通用除錯規則可轉移。
來源與維護
執行 scripts/verify.sh (在此技能的目錄中) 以一次檢查以下所有項目。
資訊截至 2026-07-22,已在儲存庫 ~/Documents/Coding Folder/Portfolio (test) 的提交 457868a 中驗證。在信任前請重新驗證:
- 模組列表與大小:
wc -l design-demos/js/*.js - 腳本載入順序:
grep -n "<script" design-demos/v4-d-hybrid.html - 哪些展示使用了共用模組:
grep -l "roll-core.js" design-demos/*.html - 頭部註解慣例仍然有效:
for f in design-demos/v4-*.html; do echo "== $f"; head -5 "$f"; done - 減少動畫閘門:
grep -n "prefers-reduced-motion\|Roll.reduced" design-demos/js/*.js - 面板可視性閘門控制:
grep -n "classList.contains('in')" design-demos/js/roll-scroll.js - Lenis 是否自行維護並正確連接:
ls design-demos/js/vendor/ && grep -n "new Lenis" design-demos/js/roll-scroll.js - GSAP 增強鉤子:
grep -n "upgradeMotion" design-demos/js/roll-core.js design-demos/v4-d-hybrid.html - 音訊靜音默認值與儲存鍵值:
grep -n "ch001_muted" design-demos/js/roll-audio.js - 零主控台錯誤標準:
grep -n "console errors" design-demos/DECISIONS.md