실시간 차트 보조지표 탭 문제 수정

This commit is contained in:
Macbook
2026-05-28 01:26:53 +09:00
parent 4f6694b206
commit 98dfb3613c
19 changed files with 801 additions and 182 deletions
+42 -15
View File
@@ -715,6 +715,7 @@ export class ChartManager {
await this.addIndicator(config, { skipLayout: true });
}
if (configs.length > 0 && this._activeIndicatorPaneIndices().size > 0) {
this._removeOrphanSubPanes();
this.resetPaneHeights(this._lastLayoutAvailableHeight);
this._notifyPaneLayout();
}
@@ -778,6 +779,8 @@ export class ChartManager {
if (this._indicatorLoadStale(loadGen)) return;
// 시리즈 제거 후 남은 빈 sub-pane 제거 (상단 orphan pane → 레이블·그래프 어긋남 방지)
this._removeOrphanSubPanes();
// 빈 pane stretch 정리 + 캔들 pane 비율 복구
this.resetPaneHeights();
this._notifyPaneLayout();
@@ -1723,6 +1726,11 @@ export class ChartManager {
}
}
/** PaneLegend 등 — 보조지표 pane DOM 배치가 끝난 뒤 레이블 위치 재동기화 */
notifyPaneLayoutChanged(): void {
this._notifyPaneLayout();
}
/**
* 차트 컨테이너 기준 각 pane 의 topY 와 height 배열 반환.
* IPaneApi.getHTMLElement() 로 pane index ↔ 화면 위치를 직접 매칭한다.
@@ -1805,22 +1813,25 @@ export class ChartManager {
getIndicatorPaneScreenLayout(id: string): { topY: number; height: number } | null {
const entry = this.indicators.get(id);
if (!entry || entry.paneIndex == null || entry.paneIndex < 2) return null;
const series = entry.seriesList[0];
if (!series) return null;
try {
const el = series.getPane().getHTMLElement();
if (!el) return null;
const rect = el.getBoundingClientRect();
const containerRect = this.container.getBoundingClientRect();
const height = Math.round(rect.height);
if (height < 12) return null;
return {
topY: Math.round(rect.top - containerRect.top),
height,
};
} catch {
return null;
const containerRect = this.container.getBoundingClientRect();
const MIN_H = 4;
for (const series of entry.seriesList) {
try {
const el = series.getPane().getHTMLElement();
if (!el) continue;
const rect = el.getBoundingClientRect();
const height = Math.round(rect.height);
if (height < MIN_H) continue;
return {
topY: Math.round(rect.top - containerRect.top),
height,
};
} catch {
/* try next series */
}
}
return null;
}
/**
@@ -2373,6 +2384,22 @@ export class ChartManager {
}
}
/** 활성 지표가 없는 sub-pane 제거 (중간·상단 orphan pane 포함) */
private _removeOrphanSubPanes(): void {
const active = this._activeIndicatorPaneIndices();
for (let i = this.chart.panes().length - 1; i >= 2; i--) {
const panes = this.chart.panes();
if (i >= panes.length) continue;
const pi = panes[i].paneIndex();
if (active.has(pi)) continue;
try {
this.chart.removePane(i);
} catch {
return;
}
}
}
/** 활성 지표가 없는 맨 끝 sub-pane 만 제거 — 단일 지표 제거 시 나머지 pane 유지 */
private _trimTrailingEmptySubPanes(): void {
for (;;) {