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