실시간 챠트 오류 수정
This commit is contained in:
@@ -942,6 +942,10 @@ html.theme-blue {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
/* 캔들 전체보기 — 보조지표 스크롤 영역 잠금 (전환 시 scrollTop 드리프트 방지) */
|
||||||
|
.tv-chart-wrap--candle-only {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
.tv-chart-wrap::-webkit-scrollbar { width: 6px; }
|
.tv-chart-wrap::-webkit-scrollbar { width: 6px; }
|
||||||
.tv-chart-wrap::-webkit-scrollbar-track { background: transparent; }
|
.tv-chart-wrap::-webkit-scrollbar-track { background: transparent; }
|
||||||
.tv-chart-wrap::-webkit-scrollbar-thumb { background: var(--bg4); border-radius: 3px; }
|
.tv-chart-wrap::-webkit-scrollbar-thumb { background: var(--bg4); border-radius: 3px; }
|
||||||
|
|||||||
@@ -347,8 +347,9 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const candleOnly = candleOnlyModeRef.current;
|
||||||
let required: number;
|
let required: number;
|
||||||
if (candleOnlyModeRef.current) {
|
if (candleOnly) {
|
||||||
mgr.applyCandleOnlyLayout(true, wrapperH);
|
mgr.applyCandleOnlyLayout(true, wrapperH);
|
||||||
required = wrapperH;
|
required = wrapperH;
|
||||||
} else {
|
} else {
|
||||||
@@ -358,14 +359,16 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
required = mgr.resetPaneHeights(wrapperH);
|
required = mgr.resetPaneHeights(wrapperH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paneLayoutClamp) {
|
|
||||||
try {
|
|
||||||
const w = wrapper.clientWidth;
|
const w = wrapper.clientWidth;
|
||||||
|
|
||||||
|
if (candleOnly || paneLayoutClamp) {
|
||||||
|
// 전체보기·미니차트: 래퍼 높이에 고정 resize (autoSize 피드백 루프·무한 스크롤 방지)
|
||||||
|
try {
|
||||||
if (w > 0 && wrapperH > 0) mgr.resize(w, wrapperH);
|
if (w > 0 && wrapperH > 0) mgr.resize(w, wrapperH);
|
||||||
} catch { /* ok */ }
|
} catch { /* ok */ }
|
||||||
}
|
container.style.height = `${wrapperH}px`;
|
||||||
|
if (candleOnly) wrapper.scrollTop = 0;
|
||||||
if (!paneLayoutClamp && required > wrapperH + 4) {
|
} else if (required > wrapperH + 4) {
|
||||||
container.style.height = `${required}px`;
|
container.style.height = `${required}px`;
|
||||||
} else {
|
} else {
|
||||||
container.style.height = '';
|
container.style.height = '';
|
||||||
@@ -979,9 +982,22 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
if (width === prevW && height === prevH) return;
|
if (width === prevW && height === prevH) return;
|
||||||
// 이전 크기가 0이었다가 유효해진 경우 (= display:none → visible 전환)
|
// 이전 크기가 0이었다가 유효해진 경우 (= display:none → visible 전환)
|
||||||
const wasHidden = prevW <= 0 || prevH <= 0;
|
const wasHidden = prevW <= 0 || prevH <= 0;
|
||||||
prevW = width; prevH = height;
|
|
||||||
if (width <= 0 || height <= 0) return;
|
if (width <= 0 || height <= 0) return;
|
||||||
|
|
||||||
|
// 캔들 전체보기: 컨테이너가 래퍼보다 커지면 즉시 클램프 (ResizeObserver ↔ autoSize 루프 차단)
|
||||||
|
if (candleOnlyModeRef.current) {
|
||||||
|
const wh = wrapperRef.current?.clientHeight ?? 0;
|
||||||
|
if (wh > 0 && height > wh + 4) {
|
||||||
|
prevW = width;
|
||||||
|
prevH = wh;
|
||||||
|
const m = managerRef.current;
|
||||||
|
if (m) applyPaneLayout(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prevW = width; prevH = height;
|
||||||
|
|
||||||
if (resizeDebounceRef.current) clearTimeout(resizeDebounceRef.current);
|
if (resizeDebounceRef.current) clearTimeout(resizeDebounceRef.current);
|
||||||
resizeDebounceRef.current = window.setTimeout(() => {
|
resizeDebounceRef.current = window.setTimeout(() => {
|
||||||
resizeDebounceRef.current = null;
|
resizeDebounceRef.current = null;
|
||||||
@@ -1426,7 +1442,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
// wrapperRef: 스크롤 영역 (overflow-y: auto → App.css .tv-chart-wrap)
|
// wrapperRef: 스크롤 영역 (overflow-y: auto → App.css .tv-chart-wrap)
|
||||||
<div
|
<div
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
className="tv-chart-wrap"
|
className={`tv-chart-wrap${candleOnlyMode ? ' tv-chart-wrap--candle-only' : ''}`}
|
||||||
style={{ flex: 1, position: 'relative', minHeight: 0 }}
|
style={{ flex: 1, position: 'relative', minHeight: 0 }}
|
||||||
onPointerMove={handleWrapperMouseMove}
|
onPointerMove={handleWrapperMouseMove}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1160,14 +1160,15 @@ ul.tnl-list.tnl-list--grid {
|
|||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 그리드형 — 상세 메타와 투자전략 구분선 사이 여백 축소 */
|
/* 그리드형 — 메타 하단 빈 공간 제거, 구분선·투자전략 간격 분리 */
|
||||||
.tnl-summary-card--grid .tnl-summary-meta {
|
.tnl-summary-card--grid .tnl-summary-meta {
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
|
margin-bottom: -4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tnl-summary-card--grid .tnl-summary-strategy-field {
|
.tnl-summary-card--grid .tnl-summary-strategy-field {
|
||||||
margin-top: -6px;
|
margin-top: 0;
|
||||||
padding-top: 2px;
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tnl-row--grid.tnl-row--unread .tnl-summary-card {
|
.tnl-row--grid.tnl-row--unread .tnl-summary-card {
|
||||||
|
|||||||
@@ -2643,9 +2643,13 @@ export class ChartManager {
|
|||||||
visible: false,
|
visible: false,
|
||||||
} as Parameters<ISeriesApi<SeriesType>['applyOptions']>[0]);
|
} as Parameters<ISeriesApi<SeriesType>['applyOptions']>[0]);
|
||||||
} catch { /* ok */ }
|
} catch { /* ok */ }
|
||||||
this.container.style.height = '';
|
|
||||||
this._resetPaneHeightsCandleFullscreen(availableHeight);
|
this._resetPaneHeightsCandleFullscreen(availableHeight);
|
||||||
this._hideAllSubPaneIndicators();
|
this._hideAllSubPaneIndicators();
|
||||||
|
const H = availableHeight && availableHeight > 0 ? availableHeight : 0;
|
||||||
|
const W = this.container.clientWidth;
|
||||||
|
if (H > 0 && W > 0) {
|
||||||
|
try { this.chart.resize(W, H); } catch { /* ok */ }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.restoreFromCandleFullscreen(availableHeight);
|
this.restoreFromCandleFullscreen(availableHeight);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user