HUAN 讙 · 開發者
ADR-0004:版面使用遞迴分割樹而不是絕對定位
狀態
已採用
背景
版面編輯器的資料模型有兩種常見選擇:
- 絕對定位:每個元素有 x、y、寬、高,可以自由拖曳與重疊。
- 遞迴分割:任何區塊都可以被切成兩塊,切出來的每一塊又可以繼續切。
決策
核心資料模型使用遞迴分割樹,比例而非像素。
type LayoutNode = { type: "split"; direction: "horizontal" | "vertical"; ratio: number; first: LayoutNode; second: LayoutNode } | { type: "slot"; content: SlotContent | null };
理由
自由拖曳會產生無效的版面。 元素重疊、留下無法解釋的空隙、超出畫布邊界——這些狀態在絕對定位模型裡全都是合法的,然後在現場的螢幕上變成一團混亂。分割樹在結構上就不可能產生重疊或空隙。
RWD 只有在比例模型下才成立。 存「左邊 1344px」的版面換一台螢幕就歪了;存「左邊 0.7」的版面在任何尺寸都是 70%。這對一個明確要支援 1080p、4K 與直式螢幕的產品是必要條件。
幾何可以完整測試。 分割樹的算繪是一個純函式:輸入樹與畫布尺寸,輸出每一塊的矩形。這讓「後台看到的和裝置播出來的一模一樣」變成可以用單元測試斷言的事,而不是靠人眼比對。
操作也比較好懂。 「把這一塊切成上下兩半」比「把這個框拖到那個座標,然後對齊」更容易做對,尤其是在需要鍵盤操作的無障礙情境下。
後果
- 做不出重疊的元素(例如浮在影片上的半透明字幕列)。這在數位看板的使用情境裡不常見,而且可以用未來的「圖層」機制補上,不需要放棄分割樹。
- 比例需要下限與上限(0.05 到 0.95)。沒有限制,使用者一不小心就會拖出 0.001 / 0.999 這種再也點不回來的版面。
- 刪除區塊實際上是「移除它的父分割」——兄弟節點會頂上來。直接刪掉插槽會留下只有一個孩子的分割節點,那種樹沒有幾何意義。
替代方案
CSS Grid 風格的網格:比自由拖曳結構化,但要表達巢狀的不對稱切分(左邊 70%,右邊再上下對切)就得引入複雜的跨列跨行語法。分割樹用兩層節點就表達完了。
自由拖曳加上吸附輔助:改善了體驗,但沒有解決根本問題——資料模型仍然允許無效狀態。