From 78271ab98c095662a4d3111ff48a229293e897cb Mon Sep 17 00:00:00 2001 From: Macbook Date: Tue, 2 Jun 2026 03:03:42 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EC=B0=A8?= =?UTF-8?q?=ED=8A=B8=20=EC=95=84=EB=9E=98=EB=A1=9C=20=EB=82=B4=EB=A0=A4?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/CandlePaneTimeAxis.tsx | 9 ++++++++- frontend/src/components/PaneSeparatorOverlay.tsx | 10 ++++++++-- frontend/src/components/TradingChart.tsx | 11 ++++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/CandlePaneTimeAxis.tsx b/frontend/src/components/CandlePaneTimeAxis.tsx index f6c615b..883ba7a 100644 --- a/frontend/src/components/CandlePaneTimeAxis.tsx +++ b/frontend/src/components/CandlePaneTimeAxis.tsx @@ -96,7 +96,13 @@ const CandlePaneTimeAxis: React.FC = ({ manager, contai const ro = new ResizeObserver(renderOverlay); ro.observe(containerEl); - const unsubLayout = manager.subscribePaneLayout(renderOverlay); + // rAF로 지연: _notifyPaneLayout 동기 호출 중 getBoundingClientRect 강제 reflow 방지 + let layoutRaf = 0; + const scheduleLayout = () => { + cancelAnimationFrame(layoutRaf); + layoutRaf = requestAnimationFrame(renderOverlay); + }; + const unsubLayout = manager.subscribePaneLayout(scheduleLayout); const unsubRange = manager.subscribeViewport(renderOverlay); const unsubFormat = subscribeChartTimeFormat(renderOverlay); const unsubCrosshair = manager.subscribeCrosshair(updateCrosshairLabel); @@ -108,6 +114,7 @@ const CandlePaneTimeAxis: React.FC = ({ manager, contai return () => { ro.disconnect(); unsubLayout(); + cancelAnimationFrame(layoutRaf); unsubRange(); unsubFormat(); unsubCrosshair(); diff --git a/frontend/src/components/PaneSeparatorOverlay.tsx b/frontend/src/components/PaneSeparatorOverlay.tsx index f5ecaf7..84ef25a 100644 --- a/frontend/src/components/PaneSeparatorOverlay.tsx +++ b/frontend/src/components/PaneSeparatorOverlay.tsx @@ -77,15 +77,21 @@ const PaneSeparatorOverlay: React.FC = ({ manager, options }) => { useEffect(() => { redraw(); - const unsub = manager.subscribePaneLayout(redraw); + let layoutRaf = 0; + const scheduleRedraw = () => { + cancelAnimationFrame(layoutRaf); + layoutRaf = requestAnimationFrame(redraw); + }; + const unsub = manager.subscribePaneLayout(scheduleRedraw); const container = manager.getContainer(); - const ro = new ResizeObserver(() => redraw()); + const ro = new ResizeObserver(scheduleRedraw); if (container) ro.observe(container); const raf1 = requestAnimationFrame(redraw); const raf2 = requestAnimationFrame(() => requestAnimationFrame(redraw)); return () => { unsub(); ro.disconnect(); + cancelAnimationFrame(layoutRaf); cancelAnimationFrame(raf1); cancelAnimationFrame(raf2); }; diff --git a/frontend/src/components/TradingChart.tsx b/frontend/src/components/TradingChart.tsx index be20d54..8ae1253 100644 --- a/frontend/src/components/TradingChart.tsx +++ b/frontend/src/components/TradingChart.tsx @@ -408,22 +408,23 @@ const TradingChart: React.FC = ({ // LWC는 chart-container에 마운트 — 우측 툴바(44px) 제외 너비로 맞춰 가격 라벨이 가리지 않음 const plotW = Math.max(0, container.clientWidth); - const plotH = Math.max(0, container.clientHeight > 0 ? container.clientHeight : wrapperH); if (candleOnly || paneLayoutClamp) { // 전체보기·미니차트: 래퍼 높이에 고정 resize (autoSize 피드백 루프·무한 스크롤 방지) container.style.height = `${wrapperH}px`; - const clampH = wrapperH > 0 ? wrapperH : plotH; try { - if (plotW > 0 && clampH > 0) mgr.resize(plotW, clampH); + if (plotW > 0 && wrapperH > 0) mgr.resize(plotW, wrapperH); } catch { /* ok */ } if (candleOnly) wrapper.scrollTop = 0; } else if (required > wrapperH + 4) { + // 보조지표 있음: 컨테이너를 required 크기로 확장해 스크롤 영역 확보 container.style.height = `${required}px`; } else { - container.style.height = ''; + // 기본 상태: 항상 명시적 픽셀 높이를 부여 (height:'' → CSS height:100% → auto 해석 문제 방지) + // autoSize:true LWC가 container.contentRect.height를 읽어 정확히 wrapperH 에 맞게 렌더링 + container.style.height = `${wrapperH}px`; try { - if (plotW > 0 && plotH > 0) mgr.resize(plotW, plotH); + if (plotW > 0 && wrapperH > 0) mgr.resize(plotW, wrapperH); } catch { /* ok */ } } // eslint-disable-next-line react-hooks/exhaustive-deps