fix(web): 分析/自动刷新后保留 K 线视窗位置
拆分手动分析与自动刷新拉数路径;全量重建用 logical 优先恢复视窗, 增量 recent 用 scroll+barDelta;避免 barSpacing 重锚与重复冻结导致往右跳。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -113,7 +113,6 @@ function updateTradingViewData(options) {
|
||||
});
|
||||
|
||||
const newBarCount = candles.length;
|
||||
const barDelta = (oldBarCount > 0 && newBarCount > 0) ? (newBarCount - oldBarCount) : 0;
|
||||
const firstBarTime = newBarCount > 0 ? candles[0].time : null;
|
||||
const lastBarTime = newBarCount > 0 ? candles[newBarCount - 1].time : null;
|
||||
const clampedVisibleRange = clampVisibleRangeToBarTimes(savedVisibleRange, firstBarTime, lastBarTime);
|
||||
@@ -336,58 +335,23 @@ function updateTradingViewData(options) {
|
||||
].filter(Boolean);
|
||||
|
||||
const vr = clampedVisibleRange || savedVisibleRange;
|
||||
const lr = savedLogicalRange;
|
||||
const savedScroll = savedScrollPosition;
|
||||
const mainChartRef = tvWidget.mainChart;
|
||||
const viewSnap = {
|
||||
logicalRange: savedLogicalRange,
|
||||
visibleRange: vr,
|
||||
scrollPosition: savedScrollPosition
|
||||
};
|
||||
|
||||
const applyPosition = function (tag) {
|
||||
let ok = false;
|
||||
// scrollToPosition 最稳;setVisibleRange 的 to 常含右侧空白会锚到最右
|
||||
if (typeof savedScroll === 'number' && mainChartRef) {
|
||||
try {
|
||||
const pos = savedScroll + (barDelta || 0);
|
||||
mainChartRef.timeScale().scrollToPosition(pos, false);
|
||||
const lrNow = mainChartRef.timeScale().getVisibleLogicalRange();
|
||||
if (lrNow) {
|
||||
charts.forEach(c => {
|
||||
try { c.timeScale().setVisibleLogicalRange(lrNow); } catch (e) {}
|
||||
});
|
||||
ok = true;
|
||||
console.log('🔄 恢复位置 scroll' + (tag || '') + ':', pos);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
if (!ok && lr && lr.from !== undefined && lr.to !== undefined && newBarCount > 0) {
|
||||
const span = Math.max(1, lr.to - lr.from);
|
||||
let to = lr.to;
|
||||
let from = lr.from;
|
||||
const maxTo = newBarCount - 1 + 8;
|
||||
if (to > maxTo) {
|
||||
to = maxTo;
|
||||
from = to - span;
|
||||
}
|
||||
if (from < -8) {
|
||||
from = -8;
|
||||
to = from + span;
|
||||
}
|
||||
const clamped = { from: from, to: to };
|
||||
charts.forEach(c => {
|
||||
try {
|
||||
c.timeScale().setVisibleLogicalRange(clamped);
|
||||
ok = true;
|
||||
} catch (e) {}
|
||||
});
|
||||
if (ok) console.log('🔄 恢复位置 logical' + (tag || '') + ':', clamped);
|
||||
}
|
||||
if (!ok && vr && vr.from !== undefined && vr.to !== undefined) {
|
||||
charts.forEach(c => {
|
||||
try {
|
||||
c.timeScale().setVisibleRange(vr);
|
||||
ok = true;
|
||||
} catch (e) {}
|
||||
});
|
||||
if (ok) console.log('🔄 恢复位置 time' + (tag || '') + ':', vr);
|
||||
}
|
||||
if (typeof restoreChartViewState !== 'function') return;
|
||||
restoreChartViewState(charts, viewSnap, {
|
||||
incremental: true,
|
||||
skipBarSpacing: true,
|
||||
oldBarCount: oldBarCount,
|
||||
newBarCount: newBarCount,
|
||||
firstBarTime: firstBarTime,
|
||||
lastBarTime: lastBarTime
|
||||
});
|
||||
if (tag) console.log('🔄 恢复位置' + tag);
|
||||
};
|
||||
|
||||
const finishPreserve = function () {
|
||||
@@ -404,8 +368,18 @@ function updateTradingViewData(options) {
|
||||
applyPosition('');
|
||||
setTimeout(function () { applyPosition('@0'); }, 0);
|
||||
setTimeout(function () { applyPosition('@50'); }, 50);
|
||||
// 增量 setData 常不触发可见时间范围回调,但价格轴会变:补刷分型竖边
|
||||
var bumpFxVert = function () {
|
||||
if (typeof window._redrawFxBoxVerticalOverlay === 'function') {
|
||||
window._redrawFxBoxVerticalOverlay();
|
||||
}
|
||||
};
|
||||
bumpFxVert();
|
||||
setTimeout(bumpFxVert, 0);
|
||||
setTimeout(bumpFxVert, 50);
|
||||
setTimeout(function () {
|
||||
applyPosition('@150');
|
||||
bumpFxVert();
|
||||
finishPreserve();
|
||||
}, 150);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user