# 設計版面

/app/layouts 是版面列表，/app/layouts/:id 是編輯器。

`/app/layouts` 是版面列表，`/app/layouts/:id` 是編輯器。

<figure class="huan-figure">
	<img src="/huan/screenshots/layout-editor.png" alt="版面編輯器" />
	<figcaption>版面編輯器：左側素材、中間預覽、右側屬性</figcaption>
</figure>

## 建立版面

先決定畫布尺寸：

| 預設        | 用途             |
| ----------- | ---------------- |
| 1920 × 1080 | 一般橫式螢幕     |
| 1080 × 1920 | 直式螢幕         |
| 3840 × 2160 | 4K               |
| 1280 × 720  | 較低解析度的裝置 |

也可以自訂，或選擇**使用裝置解析度**，直接從已配對裝置回報的顯示器資訊帶入。

## 遞迴分割

版面不是自由拖曳的畫布，而是一棵分割樹。任何區塊都可以被切成兩塊：

```text
根區塊（水平分割 70/30）
├─ 左 70%  → 影片
└─ 右 30%（垂直分割 50/50）
   ├─ 上 → 標題文字
   └─ 下 → 跑馬燈
```

- **水平分割**：兩塊左右並排。
- **垂直分割**：兩塊上下堆疊。

分割用的是**比例**而不是像素。因此同一份版面在 1080p 與 4K 上維持相同的構圖。

比例有 5% 到 95% 的限制——沒有這個限制，一不小心就會拖出再也點不回來的版面。

理由見 [ADR-0004](/huan/dev/adr/0004-recursive-split-layout)。

## 操作

| 操作           | 方式                                 |
| -------------- | ------------------------------------ |
| 選取區塊       | 點擊，或用 Tab 鍵移動焦點            |
| 水平／垂直分割 | 工具列按鈕或快捷鍵                   |
| 調整比例       | 拖曳分隔線，或在右側面板輸入數值     |
| 刪除分割       | 選取後按刪除，兄弟區塊會頂上來       |
| 放入內容       | 從左側素材面板拖入，或在右側面板選擇 |
| 交換內容       | 把一個區塊拖到另一個區塊上           |

:::tip[拖曳不是唯一的方式]

每一個拖曳操作都有鍵盤或表單的替代方式。比例可以用方向鍵微調，也可以直接輸入數字。

:::

## 區塊內容

| 類型       | 設定                                                   |
| ---------- | ------------------------------------------------------ |
| **文字**   | 內容、背景色、文字色、字級、字重、水平與垂直對齊、內距 |
| **跑馬燈** | 同文字，另加方向、速度與重複間距                       |
| **圖片**   | 素材、填滿方式（contain／cover／fill）、背景色         |
| **影片**   | 素材、填滿方式、循環、靜音、音量、背景色               |
| **網址**   | https 網址，以 iframe 顯示                             |
| **HTML**   | 上傳的 HTML 素材，以 sandbox iframe 顯示               |

字型固定使用 sans-serif，HUAN 不提供字型上傳。

填滿方式的預設是 `contain`，也就是不變形。

### 關於 iframe

:::warning[很多網站不能被嵌入]

外部網站可以用 `X-Frame-Options` 或 `Content-Security-Policy: frame-ancestors` 明確禁止被嵌入。遇到這種網站，區塊會顯示空白。

這是對方網站的安全設定，**HUAN 不會也不應該繞過它**。改用可嵌入的來源，或把內容做成上傳的 HTML。

:::

## 全域設定

- **背景色**：畫布本身的底色，也是螢幕長寬比與畫布不同時留白區域的顏色。
- **背景圖片**：可選。
- **間距**：區塊之間的距離，單位是設計畫布的 px，會跟著畫布等比縮放。

間距是從可用空間扣掉的，所以不論分幾層，所有區塊的外緣永遠貼齊畫布邊界。

## 草稿與發布

編輯器改的是**草稿**，會自動儲存。現場播的還是上一次發布的內容，所以可以放心編輯。

按下發布會建立一筆**不可變的修訂**：

```text
版面 3
├─ 修訂 12（2026-08-01）
├─ 修訂 13（2026-08-14）
└─ 修訂 14（2026-09-02）← 目前
```

裝置的目標狀態指向修訂 id，因此可以明確知道某台裝置播的是哪一版，也可以在需要時回溯。

發布前會檢查所有引用到的素材都已經就緒。有素材還在處理中或需要重新上傳時，發布會被擋下並列出是哪幾個。

## 預覽和實機一模一樣

編輯器的預覽和裝置播放器用的是**同一套版面引擎**（`@huan/layout-engine`）。

這不是為了少寫程式碼，而是為了保證兩邊一致。如果後台自己算一套、裝置再算一套，遲早會出現「後台是 70/30，實機變成 68/32」這種沒人查得出來的偏差。

幾何計算有針對 1920×1080、1280×720、3840×2160 與 1080×1920 的單元測試，斷言的是實際數值。

## 螢幕長寬比不一樣時

裝置的螢幕和設計畫布長寬比不同時，HUAN 會把整份畫布**等比縮放並置中**，剩下的區域填入版面背景色。

**不做拉伸。** 變形的看板比黑邊難看得多，而且客戶不會知道問題出在哪裡。
