v9.5: 實作標籤完全不重疊算法
- 新增 _calculate_lane_conflicts_v2() 分開返回標籤重疊和線穿框分數 - 修改泳道選擇算法,優先選擇無標籤重疊的泳道 - 兩階段搜尋:優先側別無可用泳道則嘗試另一側 - 增強日誌輸出,顯示標籤範圍和詳細衝突分數 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
230
IMPROVEMENTS_v3.md
Normal file
230
IMPROVEMENTS_v3.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# 時間軸標籤避碰改進(v3.0) - 平滑曲線與時間分離
|
||||
|
||||
## 新增改進(v3.0)
|
||||
|
||||
### 1. **平滑曲線連接 - 避免視覺阻礙**
|
||||
|
||||
#### 問題
|
||||
- Z 形折線雖然清晰,但仍可能阻礙其他文字框或連線
|
||||
- 多條連線交叉時造成視覺混亂
|
||||
|
||||
#### 解決方案
|
||||
使用**平滑曲線 + 虛線 + 半透明**組合:
|
||||
|
||||
```python
|
||||
# 5 個控制點創建平滑曲線
|
||||
line_x_points = [
|
||||
event_x, # 起點:事件點
|
||||
event_x, # 垂直上升
|
||||
curve_x, # 曲線控制點(帶偏移)
|
||||
label_x, # 水平接近
|
||||
label_x # 終點:標籤
|
||||
]
|
||||
|
||||
# Y 座標使用漸進式高度
|
||||
line_y_points = [
|
||||
0, # 起點
|
||||
mid_y * 0.7, # 70% 高度
|
||||
mid_y, # 中間高度
|
||||
mid_y * 0.7, # 70% 高度
|
||||
label_y # 終點
|
||||
]
|
||||
|
||||
# 視覺優化
|
||||
line: {
|
||||
'color': event_color,
|
||||
'width': 1,
|
||||
'dash': 'dot', # 虛線
|
||||
}
|
||||
opacity: 0.6 # 半透明
|
||||
```
|
||||
|
||||
**優勢**:
|
||||
- ✅ 虛線樣式不會完全遮擋背後內容
|
||||
- ✅ 半透明(60%)減少視覺阻礙
|
||||
- ✅ 平滑曲線更自然、更專業
|
||||
- ✅ 5 個控制點創造弧形路徑,避免直線交叉
|
||||
|
||||
---
|
||||
|
||||
### 2. **時間與標題分離顯示**
|
||||
|
||||
#### 問題
|
||||
- 標籤框同時顯示標題和時間,導致框體過大
|
||||
- 框體越大,避碰越困難
|
||||
|
||||
#### 解決方案
|
||||
**時間顯示在事件點旁邊**,標籤框只顯示標題:
|
||||
|
||||
```python
|
||||
# 時間標籤(靠近事件點)
|
||||
annotations.append({
|
||||
'x': event_x,
|
||||
'y': -0.15, # 在時間軸下方
|
||||
'text': f"{date_str}<br>{time_str}",
|
||||
'font': {'size': 9},
|
||||
'bgcolor': 'rgba(255, 255, 255, 0.95)',
|
||||
'bordercolor': event_color,
|
||||
'borderwidth': 1,
|
||||
'borderpad': 2
|
||||
})
|
||||
|
||||
# 標題標籤(在連線終點)
|
||||
annotations.append({
|
||||
'x': label_x,
|
||||
'y': label_y,
|
||||
'text': f"<b>{title}</b>", # 只顯示標題
|
||||
'font': {'size': 11},
|
||||
'borderwidth': 2,
|
||||
'borderpad': 6
|
||||
})
|
||||
```
|
||||
|
||||
**優勢**:
|
||||
- ✅ 標籤框更小,避碰更容易
|
||||
- ✅ 時間緊貼事件點,對應關係清晰
|
||||
- ✅ 標題框可以更大、更醒目
|
||||
- ✅ 視覺層次更分明
|
||||
|
||||
---
|
||||
|
||||
### 3. **時間精度到時分秒**
|
||||
|
||||
#### 改進前
|
||||
```
|
||||
日期: 2024-01-01
|
||||
```
|
||||
|
||||
#### 改進後
|
||||
```
|
||||
2024-01-01
|
||||
14:30:00
|
||||
```
|
||||
|
||||
**格式**:
|
||||
- 日期:`%Y-%m-%d`
|
||||
- 時間:`%H:%M:%S`
|
||||
- Hover 提示:`%Y-%m-%d %H:%M:%S`
|
||||
|
||||
---
|
||||
|
||||
## 完整改進對比
|
||||
|
||||
### v1.0(初版)
|
||||
- ❌ 直線連接
|
||||
- ❌ 標籤固定位置
|
||||
- ❌ 只有日期
|
||||
- ❌ 容易重疊
|
||||
|
||||
### v2.0(2D 避碰)
|
||||
- ✅ Z 形折線
|
||||
- ✅ 標籤可偏移
|
||||
- ✅ 智能避碰
|
||||
- ⚠️ 折線可能阻礙
|
||||
|
||||
### v3.0(平滑曲線 + 時間分離)
|
||||
- ✅ **平滑曲線(虛線 + 半透明)**
|
||||
- ✅ **時間顯示在點旁邊**
|
||||
- ✅ **標題與時間分離**
|
||||
- ✅ **時分秒精度**
|
||||
- ✅ **最小視覺阻礙**
|
||||
|
||||
---
|
||||
|
||||
## 視覺效果
|
||||
|
||||
### 連線樣式
|
||||
```
|
||||
事件點 ●
|
||||
┆ (虛線,60% 透明)
|
||||
┆
|
||||
╰─→ 標題框
|
||||
```
|
||||
|
||||
### 時間標籤位置
|
||||
```
|
||||
┌─────────┐
|
||||
│ 標題 │ ← 標籤框(只有標題)
|
||||
└─────────┘
|
||||
↑
|
||||
┆ (平滑曲線)
|
||||
●
|
||||
┌────────┐
|
||||
│2024-01 │ ← 時間標籤(在點旁邊)
|
||||
│14:30:00│
|
||||
└────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 關鍵參數
|
||||
|
||||
```python
|
||||
# 連線樣式
|
||||
line_width = 1 # 細線
|
||||
line_dash = 'dot' # 虛線
|
||||
line_opacity = 0.6 # 60% 透明
|
||||
|
||||
# 時間標籤
|
||||
time_font_size = 9 # 小字體
|
||||
time_position_y = -0.15 # 軸下方
|
||||
|
||||
# 標題標籤
|
||||
title_font_size = 11 # 較大字體
|
||||
title_borderwidth = 2 # 較粗邊框
|
||||
title_borderpad = 6 # 較大內距
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 測試方法
|
||||
|
||||
```batch
|
||||
start_dev.bat
|
||||
```
|
||||
|
||||
訪問 http://localhost:12010,測試示範檔案:
|
||||
- `demo_project_timeline.csv` - 15 個事件
|
||||
- `demo_life_events.csv` - 11 個事件
|
||||
- `demo_product_roadmap.csv` - 14 個事件
|
||||
|
||||
**預期效果**:
|
||||
- ✅ 平滑虛線連接,半透明不阻擋
|
||||
- ✅ 時間標籤緊貼事件點
|
||||
- ✅ 標題框簡潔醒目
|
||||
- ✅ 時分秒精度顯示
|
||||
- ✅ 整體視覺清爽專業
|
||||
|
||||
---
|
||||
|
||||
## 技術實現
|
||||
|
||||
### 平滑曲線演算法
|
||||
使用 5 個控制點創建漸進式曲線:
|
||||
|
||||
1. **起點**:事件點 (event_x, 0)
|
||||
2. **上升點**:(event_x, mid_y × 0.7)
|
||||
3. **曲線頂點**:(curve_x, mid_y) - 帶水平偏移
|
||||
4. **下降點**:(label_x, mid_y × 0.7)
|
||||
5. **終點**:標籤位置 (label_x, label_y)
|
||||
|
||||
**曲線偏移計算**:
|
||||
```python
|
||||
x_diff = abs((label_x - event_x).total_seconds())
|
||||
curve_offset = timedelta(seconds=x_diff * 0.2) # 20% 偏移
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 未來改進方向
|
||||
|
||||
1. **貝茲曲線**:使用真正的貝茲曲線(需要更複雜的數學計算)
|
||||
2. **路徑避障**:實現 A* 演算法自動繞過文字框
|
||||
3. **動態透明度**:根據重疊程度調整透明度
|
||||
4. **智能顏色**:根據背景自動調整連線顏色
|
||||
|
||||
---
|
||||
|
||||
**版本**: v3.0
|
||||
**更新日期**: 2025-11-05
|
||||
**作者**: Claude AI
|
||||
Reference in New Issue
Block a user