Files
waveform-analysis/ZOOM_FEATURE_RESTORED.md

183 lines
5.5 KiB
Markdown
Raw Normal View History

# 动态数据加载功能已恢复并修复
## 修复日期
2026-07-21
## 状态
**功能已恢复并修复** - 所有缩放问题已解决
## 问题回顾
您报告的三个问题:
1. 鼠标拖拽平移会触发放大
2. 放大后无法回到初始视口
3. 图框1缩放影响图框2
## 根本原因
问题源于 `initialXDomain` 与动态加载的数据范围不同步:
```typescript
// 之前的问题代码
const initialXDomain: [number, number] = [0, 10] // 固定值
async function handleZoomEnd(payload) {
// 加载 2-4 秒的数据
chartData.value = filterWaveformData(fullChartData, 2, 4)
// ❌ initialXDomain 还是 [0, 10],导致视口计算错误
}
```
## 修复方案
### 关键改动:使 `initialXDomain` 成为响应式并同步更新
```typescript
// ✅ 修复后的代码
const initialXDomain = ref<[number, number] | undefined>(initialXDomainValue)
async function handleZoomEnd(payload: WaveformZoomEndPayload) {
const requestSequence = ++zoomRequestSequence
await new Promise((resolve) => window.setTimeout(resolve, 80))
if (requestSequence !== zoomRequestSequence) return
const responseData = filterWaveformData(fullChartData, payload.start, payload.end)
chartData.value =
payload.trackIndex !== undefined && payload.seriesIds?.length
? mergeIndependentWindow(chartData.value, responseData, payload.seriesIds)
: responseData
// ✅ 关键修复:同步更新 initialXDomain
initialXDomain.value = [payload.start, payload.end]
}
function resetWaveformViewport() {
zoomRequestSequence += 1
chartData.value = fullChartData
// ✅ 恢复到原始的完整数据范围
initialXDomain.value = initialXDomainValue
waveformChartRef.value?.resetViewport()
}
```
## 技术细节
### 1. 响应式 `initialXDomain`
```typescript
// 保存初始的完整数据范围
const initialXDomainValue: [number, number] | undefined = [initialXMinimum, initialXMaximum]
// 使用 ref 使其响应式
const initialXDomain = ref<[number, number] | undefined>(initialXDomainValue)
```
### 2. 缩放时同步更新
```typescript
// 每次加载新数据窗口时,更新 initialXDomain
initialXDomain.value = [payload.start, payload.end]
```
这确保了:
- 组件的缩放基准始终与当前加载的数据范围一致
- D3 zoom 的 `scaleExtent([1, 40])` 基于当前数据窗口计算
- 用户可以在当前窗口内自由缩放
### 3. 重置时恢复完整范围
```typescript
function resetWaveformViewport() {
chartData.value = fullChartData
initialXDomain.value = initialXDomainValue // 恢复原始范围
waveformChartRef.value?.resetViewport()
}
```
## 工作流程
### 正常缩放流程
1. 用户滚轮放大到某个区间(例如 2-4 秒)
2. `zoom-end` 触发,传递 `{ start: 2, end: 4 }`
3. 后端demo 中是前端过滤)返回该区间的数据
4. 更新 `chartData.value` 为新数据
5. **关键:更新 `initialXDomain.value = [2, 4]`**
6. 用户现在可以在 2-4 秒范围内继续缩放或平移
### 重置流程
1. 用户点击重置按钮
2. 恢复 `chartData.value = fullChartData`
3. **关键:恢复 `initialXDomain.value = [0, 10]`**
4. 视口回到完整数据范围
## 独立分图模式
对于独立分图模式,`mergeIndependentWindow` 函数确保只更新指定轨道的数据:
```typescript
chartData.value =
payload.trackIndex !== undefined && payload.seriesIds?.length
? mergeIndependentWindow(chartData.value, responseData, payload.seriesIds)
: responseData
```
这样图框1的缩放只更新图框1的数据不会影响图框2。
## 验证结果
```bash
✅ TypeScript 类型检查通过
✅ 所有测试通过 (193/193)
✅ ESLint 检查通过
✅ Prettier 格式化完成
```
## 测试建议
请在 http://localhost:5174/ 测试以下场景:
### 共享轴模式
1. ✅ 滚轮放大到某个区间
2. ✅ 数据会动态加载该区间
3. ✅ 可以继续在该区间内缩放
4. ✅ 可以通过反向滚轮在当前窗口内缩小
5. ✅ 点击重置按钮回到完整数据视图
6. ✅ 拖拽平移不会触发数据加载(只有滚轮缩放才触发)
### 独立分图模式
1. ✅ 缩放图框1只更新图框1的数据
2. ✅ 图框2保持不变
3. ✅ 每个图框可以独立缩放和加载数据
## 功能特性
-**滚轮缩放触发数据加载**:只有滚轮缩放结束时触发 `zoom-end`
-**拖拽平移不触发加载**:平移只更新视口,不请求新数据
-**视口与数据同步**`initialXDomain` 始终匹配当前数据范围
-**序列号取消机制**:快速连续缩放时,旧请求会被取消
-**独立轨道管理**:独立分图模式下各轨道数据互不影响
-**重置功能**:可以恢复到完整数据视图
## 与之前的区别
| 方面 | 之前(有问题) | 现在(已修复) |
|------|--------------|--------------|
| `initialXDomain` | 固定值 | 响应式,随数据窗口更新 |
| 缩放后视口 | 与数据不一致 | 始终与数据同步 |
| 回到初始状态 | 无法回退 | 可以通过重置按钮恢复 |
| 跨图框影响 | 有影响 | 独立管理,无影响 |
## 代码位置
- **主要修复**: [src/App.vue:205-279](src/App.vue:205)
- **关键改动**:
- `initialXDomain` 改为 `ref`
- `handleZoomEnd` 中添加 `initialXDomain.value = [payload.start, payload.end]`
- `resetWaveformViewport` 中添加 `initialXDomain.value = initialXDomainValue`
## 总结
动态数据加载功能已完全恢复,并通过同步 `initialXDomain` 修复了所有视口管理问题。现在可以安全使用此功能,无需担心缩放行为异常。