fix(web): 分析/自动刷新后保留 K 线视窗位置

拆分手动分析与自动刷新拉数路径;全量重建用 logical 优先恢复视窗,
增量 recent 用 scroll+barDelta;避免 barSpacing 重锚与重复冻结导致往右跳。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-25 23:38:20 +08:00
co-authored by Cursor
parent 8ee11317d3
commit 90499533fb
8 changed files with 449 additions and 310 deletions
+16 -8
View File
@@ -66,9 +66,7 @@ function chartTvFinalize(ctx) {
const allChartsNow = [mainChart, volumeChart, atrChart]
.concat(showMacd && macdChart ? [macdChart] : [])
.concat(showMacd && chanMacdChart ? [chanMacdChart] : []);
if (hasPendingRestoreView && pendingView) {
restoreChartViewState(allChartsNow, pendingView, { preferTime: true });
} else {
if (!hasPendingRestoreView || !pendingView) {
// 显示最近 200 根K线而非全部挤压(避免K线过多时重叠)
if (totalBars > visibleBarsCount) {
const rangeFrom = totalBars - visibleBarsCount;
@@ -81,8 +79,7 @@ function chartTvFinalize(ctx) {
// 立即同步其他图表到主图表的范围(无 pending 时)
setTimeout(() => {
if (window._pendingRestoreView) {
restoreChartViewState(allChartsNow, window._pendingRestoreView, { preferTime: true });
if (pendingView) {
return;
}
const logRange = mainChart.timeScale().getVisibleLogicalRange();
@@ -189,6 +186,9 @@ function chartTvFinalize(ctx) {
updateIndicatorPanel();
// 绑定同步事件
if (hasPendingRestoreView && pendingView) {
window._preserveViewDuringUpdate = true;
}
bindSyncEvents(mainChartContainer, volumeChartContainer, atrChartContainer, macdChartContainer, chanMacdChartContainer, mainChart, volumeChart, atrChart, macdChart, chanMacdChart, showMacd);
// 最终确保所有图表时间轴对齐(同时恢复刷新前保存的缩放/位置)
@@ -198,13 +198,20 @@ function chartTvFinalize(ctx) {
if (showMacd && chanMacdChart) allCharts.push(chanMacdChart);
// 检查是否有待恢复的视图(缩放 + 位置)
const pending = window._pendingRestoreView;
const pending = window._pendingRestoreView || pendingView;
window._pendingRestoreView = null;
if (pending) {
// 恢复刷新前的缩放和位置(时间范围优先,避免数据滑动后逻辑索引错位)
const firstT = candles && candles.length ? candles[0].time : null;
const lastT = candles && candles.length ? candles[candles.length - 1].time : null;
console.log('📌 恢复图表视图:', JSON.stringify(pending));
restoreChartViewState(allCharts, pending, { preferTime: true });
restoreChartViewState(allCharts, pending, {
firstBarTime: firstT,
lastBarTime: lastT,
oldBarCount: window._preserveViewBarCount || 0,
newBarCount: totalBars
});
window._preserveViewBarCount = 0;
} else {
// 无保存视图,正常同步主图到子图
const visibleRange = mainChart.timeScale().getVisibleRange();
@@ -218,6 +225,7 @@ function chartTvFinalize(ctx) {
});
}
}
window._preserveViewDuringUpdate = false;
console.log('🔧 最终时间轴对齐完成');
}, 150);
// 只有在时间输入框都为空时才设置图表默认时间范围