# 時間軸標籤避碰改進(v2.0) ## 問題 原始實現中,標籤只有簡單的上下(或左右)交錯,導致當事件密集時會出現文字框重疊、遮蔽的問題。 ## 解決方案 v2.0 - 智能 2D 避碰 + 折線連接 ### 1. **二維智能避碰演算法** ```python def _calculate_label_positions(events, start_date, end_date): - 計算每個標籤在時間軸上的 2D 佔用範圍 - 偵測水平重疊衝突 - 嘗試水平偏移(左右移動標籤) - 如果同層無法容納,自動分配到新層級 - 支援無限層級擴展 ``` **避碰策略**: 1. 先嘗試在同一層級無偏移放置 2. 如有衝突,嘗試向左偏移 (1x, 2x, 3x 間距) 3. 仍有衝突,嘗試向右偏移 (1x, 2x, 3x 間距) 4. 都無法容納,創建新層級 ### 2. **折線連接(Polyline)** - **舊版本**:直線連接(事件點 → 標籤) - **新版本**:Z 形折線連接 - 水平時間軸:垂直線 → 水平線 → 垂直線 - 垂直時間軸:水平線 → 垂直線 → 水平線 - 使用 Plotly `path` 繪製平滑折線 **折線路徑(水平時間軸)**: ``` 事件點 (event_x, 0) ↓ 垂直線 中間點 (event_x, mid_y) → 水平線 轉折點 (label_x, mid_y) ↓ 垂直線 標籤位置 (label_x, label_y) ``` ### 3. **動態標籤位置** - **垂直位置**:根據層級自動計算(上下交錯) - **水平位置**:根據避碰演算法動態偏移 - **連接線**:自動調整路徑適應偏移 ### 4. **關鍵參數** - `label_width_ratio = 0.08`: 標籤寬度約為時間軸的 8%(增加) - `min_horizontal_gap = 0.015`: 最小水平間距為時間軸的 1.5% - `layer_spacing = 0.6`: 層級間距(增加) - 動態 Y/X 軸範圍調整 ### 5. **效果** - ✅ 2D 智能避碰(垂直 + 水平) - ✅ 標籤可以左右偏移避免重疊 - ✅ 使用折線優雅連接標籤與事件點 - ✅ 根據事件密度自動調整層級數 - ✅ 視覺更清晰、更專業 ## 視覺改進對比 ### 舊版本 - ❌ 只有垂直避碰(上下層級) - ❌ 標籤 x 位置固定,無法偏移 - ❌ 直線連接,密集時會交叉 - ❌ 容易出現重疊 ### 新版本 v2.0 - ✅ 2D 避碰(垂直層級 + 水平偏移) - ✅ 標籤可動態左右移動 - ✅ Z 形折線連接,路徑清晰 - ✅ 智能避免重疊 ## 調整建議 如果標籤仍有重疊,可調整以下參數(在 `backend/renderer_timeline.py`): ```python # 第 80 行:增加標籤寬度估計(更保守) label_width_ratio = 0.10 # 從 0.08 增加到 0.10 # 第 84 行:增加最小水平間距 min_horizontal_gap = total_seconds * 0.02 # 從 0.015 增加到 0.02 # 第 226/420 行:增加層級間距 layer_spacing = 0.8 # 從 0.6 增加到 0.8 ``` ## 測試方法 ```batch start_dev.bat ``` 然後訪問 http://localhost:12010 並測試三個示範檔案。 ## 技術細節 ### 折線路徑格式 使用 SVG Path 語法: - `M x,y`:移動到起點 - `L x,y`:直線到指定點 範例: ``` M 2024-01-15,0 L 2024-01-15,0.3 L 2024-01-16,0.3 L 2024-01-16,0.6 ``` ### 避碰演算法複雜度 - 時間複雜度:O(n × m × k) - n = 事件數 - m = 平均層級數 - k = 偏移嘗試次數(最多7次) - 空間複雜度:O(n × m) ### 改進方向 未來可考慮: 1. 使用力導向演算法優化標籤位置 2. 支援標籤尺寸動態計算(根據文字長度) 3. 添加標籤碰撞預覽功能