iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0
Vibe Coding

使用 Vibe Coding 開發一套 Tutting 模擬器吧!系列 第 11

📐DAY 11 | 重構控制面板:分頁收納、一鍵隱藏與彈性高度調整

  • 分享至 

  • xImage
  •  

在前幾天的開發中,我們陸續加入了 XBOT 骨架控制、32 種 Easing 緩動曲線、BPM 計時器與 Keyframe 時間軸清單。

然而,隨著功能越來越豐富,程式的底部控制面板也變得越來越膨脹,所有清單通通堆疊在一起,把畫面下半部遮得嚴嚴實實,嚴重影響了觀賞虛擬舞者幾何姿勢的體驗!

為了提升 UX 體驗,今天 DAY 12專注於控制面板的結構重構與 UX 大修!

https://ithelp.ithome.com.tw/upload/images/20260831/20144288mbSaZIcE06.jpg

如何與 AI 討論重構程式的UI 與UX?

與 AI 討論 UI/UX 重構時,溝通的品質會直接影響輸出品質。以下是一些實用的做法:

1. 先給脈絡,不要直接丟需求

與其說「幫我改善這個介面」,不如提供 目前的程式碼、截圖或錄影(讓 AI 看到實際畫面)

2. 拆解「UI」與「UX」分開討論

這兩者常被混為一談,但問法不同:

  • UX 問題(流程、資訊架構)→ 適合先用文字描述使用者情境:「使用者從進入頁面到完成結帳要點幾次?每一步在想什麼?」
  • UI 問題(視覺、樣式)→ 適合搭配截圖或線框圖,直接指出「這裡的間距太擠」「按鈕層級不清楚」

3. 用「小步迭代」取代「一次重構全部」

大範圍重構容易讓 AI 給出籠統建議。更有效的方式:

  • 先請 AI 做啟發式評估(heuristic review),列出問題但先不動手改
  • 針對其中 1-2 個問題深入討論解法與取捨
  • 逐步套用,每次修改後回饋實際效果

4. 明確要求「取捨說明」而非只要答案

好的提問方式,例如:

「這個表單目前是單頁,我想改成分步驟。請給我兩種方案,並說明各自在轉換率、開發成本、使用者認知負擔上的優缺點。」

這樣比「幫我改成分步驟表單」得到更有參考價值的討論,而不是 AI 直接猜一個答案。

5. 善用比較與參考案例

如果你有喜歡的介面(如某個知名 App 的某個流程),直接指出「像 Notion 的側邊欄那種收合方式」,比抽象描述更精準。

三大 UX 重構成果

我們透過優化 HTML 容器結構、CSS Flexbox 佈局與事件監聽,實現了以下三大功能:

1. 分頁收納系統

將原本攤平堆疊的介面拆解為「常駐區」與「分頁區」:

  • 常駐區(永遠可見):包含主控列(播放/BPM/隨機/重置)與選取狀態列(#selectedBar)。讓你在調整關節角度時,能即時看到數值回饋。
  • 三大分頁:
    • 姿勢庫(Poses):收納快捷姿勢按鈕列(#poseBtns)。
    • 時間軸(Timeline):包含拍點控制列、Easing 選擇器與 Keyframe 清單(#kfList)。
    • JSON:收納數據導入與導出面板,切換至此分頁時自動觸發 refreshJsonArea() 刷新內容。
  • 狀態記憶:使用 localStorage 記錄上次停留的分頁,重新整理頁面後自動恢復。

2. 全局介面隱藏

  • 右上角標籤:在面板右上角外側新增「隱藏面板 ▾」小標籤,一鍵收起整個控制區。
  • 右下角喚回鈕:面板隱藏後,右下角浮現「☰ 面板」按鈕以隨時呼叫回介面。
  • 快捷鍵 H / h:支援鍵盤快捷鍵切換。防呆機制:當使用者在 input 或 textarea 輸入文字時自動停用快捷鍵,避免輸入 BPM 或 JSON 時誤觸。

3. 彈性面板高度拖曳

  • 頂部拖曳把手:在面板頂部新增橫條 Handle,支援 Pointer Events(pointerdown/pointermove/pointerup),完美兼容滑鼠與行動裝置觸控。
  • 動態比例記憶:高度限制在 160px 至視窗 85% 之間。將面板高度換算為視窗高度比例存入 localStorage,在跨裝置或調整視窗大小(Resize)時自動等比例換算。
  • 雙擊重置:雙擊 Handle 可快速重置回預設的 46% 視窗高度。

https://ithelp.ithome.com.tw/upload/images/20260822/20144288Vruc0cPOvz.png

結語:流暢的 UX 是創作的基石

透過這次的介面重構,我們的 3D 模擬器不僅能全螢幕無死角展示 Tutting 的幾何姿態,更讓動作編排與 Keyframe 調校變得無比順暢!


底部控制面板優化的Prompt如下:

# Prompt:底部控制面板優化(分頁收納/隱藏/可調高度)
---
現況問題:

1. 所有區塊攤平堆疊在同一個面板裡,沒有分類收納。
2. 沒有任何「整個面板隱藏」的機制,會一直佔用畫面下方、擋住 3D 視角。
3. 面板高度用固定的 `max-height`(例如 `60vh`),拍點清單一多會把面板撐爆,高度無法依需求調整。

## 目標

在**不改動任何既有互動邏輯**(IK/姿勢/播放/Keyframe 的行為)的前提下,只調整「容器結構+樣式+新增的 UI 控制」,完成以下三項:

### 1. 分頁收納(Tabs)
- 面板拆成「常駐區」+「分頁區」:
  - 常駐區(永遠可見,不進分頁):主控列 + 選取狀態列(`#selectedBar`)。理由:使用者拖曳關節環時需要即時看到角度回饋,這塊不能被藏起來。
  - 分頁區:至少 3 個分頁 —「姿勢庫」(poseBtns)、「JSON」(原本用按鈕 toggle 顯示的 jsonPanel,改成分頁)、「時間軸」(Keyframe 控制列 + Easing 列 + kfList)。
- 分頁列 `.tabBtn` 用底線樣式(`border-bottom`)標示 active 狀態,不用背景色塊。
- 切換分頁時,若切到 JSON 分頁要自動刷新 `#jsonArea` 內容(呼叫既有的 `refreshJsonArea()`)。
- 用 `localStorage`(key: `tuttingActiveTab`)記住使用者上次停留的分頁,重新整理後恢復。

### 2. 介面隱藏(整體顯示/隱藏)
- 面板右上角加一顆「隱藏面板 ▾」按鈕(`#uiHideBtn`,用 `position:absolute; top:-28px` 貼在面板外側上緣,像個小標籤)。
- 面板隱藏後,右下角浮現一顆「☰ 面板」按鈕(`#uiShowBtn`)把面板叫回來。
- 加鍵盤快速鍵 `H`/`h` 切換顯示/隱藏。**要防呆**:如果目前焦點在 `input`/`textarea`/`select`(例如正在打 BPM 或編輯 JSON),按 H 不要觸發切換。
- 隱藏狀態用 `localStorage`(key: `tuttingUIHidden`)記住,重新整理後維持上次狀態。
- 面板顯示時用 `display:flex`(不是 `block`,因為容器改用 flex 直向排版),隱藏用 `display:none`。

### 3. 面板高度可手動調整
- 面板頂部(分頁列與常駐區之上)加一條可拖曳把手 `#uiResizeHandle`,樣式為置中的小橫條(grip),`cursor:ns-resize`,hover/拖曳中要有視覺回饋(變色、變寬)。
- 用 Pointer Events(`pointerdown`/`pointermove`/`pointerup`,非 mousedown,才能同時支援觸控)實作拖曳:
  - 往上拖(`clientY` 變小)面板變高,往下拖變矮。
  - 拖曳中即時更新面板高度(`ui.style.height`),放開時才寫入 `localStorage`。
  - 拖曳中在 `<body>` 加一個 class(例如 `uiResizing`)把整個頁面游標鎖定成 `ns-resize`,避免拖曳時滑過其他元素游標一直跳。
- 高度限制:最低約 `160px`(保證常駐區+分頁列不會被壓爆),最高約視窗高度的 `85%`(不能整個蓋住畫面)。
- 高度記憶:存成「面板高度 / 視窗高度」的比例(而非死的 px 值),存在 `localStorage`(key 例如 `tuttingUIHeightRatio`)。頁面載入、以及瀏覽器視窗 `resize` 時都要依這個比例重新換算成新的 px 高度,維持跨裝置/跨視窗大小的相對比例一致。
- 雙擊把手可重置回預設高度(例如視窗高度的 `46%`)。
- 面板容器需要改成 `display:flex; flex-direction:column`,內部三塊(常駐區 `flex:0 0 auto`、分頁列 `flex:0 0 auto`、分頁內容區 `flex:1 1 auto; overflow-y:auto; min-height:0`)用 flex 自動分配剩餘空間,這樣拖曳改變面板總高度時,分頁內容區會自動跟著伸縮並在內部捲動,不用額外處理每個分頁的高度。
---

上一篇
📐DAY 10 | 注入 32 種 Easing 曲線與BPM舞蹈靈魂!!!
系列文
使用 Vibe Coding 開發一套 Tutting 模擬器吧!11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言