일목균형표 수정
This commit is contained in:
@@ -51,6 +51,8 @@ import CandlePaneControls from './CandlePaneControls';
|
||||
import { getKoreanName } from '../utils/marketNameCache';
|
||||
import { DEFAULT_DISPLAY_TIMEZONE } from '../utils/timezone';
|
||||
import { classifyIndicatorChartChange, singleIndParamKey } from '../utils/indicatorChartSync';
|
||||
import type { ChartPaneSeparatorOptions } from '../types/chartPaneSeparator';
|
||||
import PaneSeparatorOverlay from './PaneSeparatorOverlay';
|
||||
|
||||
interface TradingChartProps {
|
||||
bars: OHLCVBar[];
|
||||
@@ -126,6 +128,8 @@ interface TradingChartProps {
|
||||
seriesPriceLabelsEnabled?: boolean;
|
||||
/** 실시간 차트 화면 표시 여부 — false 이면 숨김 중 무거운 재로드 지연 */
|
||||
chartVisible?: boolean;
|
||||
/** pane(캔들·거래량·보조지표) 구분선 */
|
||||
paneSeparatorOptions?: ChartPaneSeparatorOptions;
|
||||
}
|
||||
|
||||
const TradingChart: React.FC<TradingChartProps> = ({
|
||||
@@ -156,6 +160,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
showHoverToolbar = true,
|
||||
seriesPriceLabelsEnabled = true,
|
||||
chartVisible = true,
|
||||
paneSeparatorOptions,
|
||||
}) => {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const wrapperRef = useRef<HTMLDivElement>(null); // 스크롤 래퍼
|
||||
@@ -207,6 +212,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
const prevSortedPKRef = useRef<string>(''); // 순서 무관 paramKey (reorder 감지용)
|
||||
const prevIndicatorsListRef = useRef<IndicatorConfig[]>(indicators);
|
||||
const indicatorSyncInFlightRef = useRef(false);
|
||||
const indicatorReloadGenRef = useRef(0);
|
||||
const prevMarket = useRef<string>(market);
|
||||
const prevMarketTf = useRef<Timeframe>(timeframe);
|
||||
const lastAppliedMarketRef = useRef<string>('');
|
||||
@@ -281,6 +287,11 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
managerRef.current?.setSeriesPriceLabelsEnabled(seriesPriceLabelsEnabled);
|
||||
}, [seriesPriceLabelsEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!paneSeparatorOptions) return;
|
||||
managerRef.current?.setPaneSeparatorOptions(paneSeparatorOptions);
|
||||
}, [paneSeparatorOptions]);
|
||||
|
||||
/**
|
||||
* pane 높이 재배분 + 스크롤 컨테이너 확장
|
||||
*
|
||||
@@ -409,18 +420,27 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
) => {
|
||||
const cover = createIndicatorReloadCover(containerRef.current);
|
||||
const savedLR = mgr.getVisibleLogicalRange();
|
||||
const reloadGen = ++indicatorReloadGenRef.current;
|
||||
|
||||
indicatorSyncInFlightRef.current = true;
|
||||
void mgr.reloadIndicatorsOnly(inds).then(() => {
|
||||
if (reloadGen !== indicatorReloadGenRef.current) {
|
||||
fadeOutIndicatorReloadCover(cover);
|
||||
return;
|
||||
}
|
||||
afterIndicatorPaneMutation(mgr);
|
||||
requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||
if (reloadGen !== indicatorReloadGenRef.current) {
|
||||
fadeOutIndicatorReloadCover(cover);
|
||||
return;
|
||||
}
|
||||
restoreLogicalRange(mgr, savedLR);
|
||||
fadeOutIndicatorReloadCover(cover);
|
||||
indicatorSyncInFlightRef.current = false;
|
||||
onComplete?.();
|
||||
}));
|
||||
});
|
||||
}, [applyPaneLayout, afterIndicatorPaneMutation, restoreLogicalRange]);
|
||||
}, [afterIndicatorPaneMutation, restoreLogicalRange]);
|
||||
|
||||
const queueFullReload = useCallback(() => {
|
||||
if (!chartVisibleRef.current) return;
|
||||
@@ -635,6 +655,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
mgr.setVolumeVisible(false, wrapperH > 0 ? wrapperH : undefined);
|
||||
}
|
||||
mgr.setSeriesPriceLabelsEnabled(seriesPriceLabelsEnabled);
|
||||
if (paneSeparatorOptions) mgr.setPaneSeparatorOptions(paneSeparatorOptions);
|
||||
onManagerReady(mgr);
|
||||
|
||||
const unsub = mgr.subscribeCrosshair((p: MouseEventParams<Time>) => {
|
||||
@@ -1251,6 +1272,12 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
||||
onClose={() => setCtxMenu(null)}
|
||||
/>
|
||||
)}
|
||||
{chartMgr && paneSeparatorOptions && (
|
||||
<PaneSeparatorOverlay
|
||||
manager={chartMgr}
|
||||
options={paneSeparatorOptions}
|
||||
/>
|
||||
)}
|
||||
{chartMgr && (
|
||||
<DrawingCanvas
|
||||
manager={chartMgr}
|
||||
@@ -1403,7 +1430,7 @@ function sortedParamKey(inds: IndicatorConfig[]): string {
|
||||
*/
|
||||
function styleKey(inds: IndicatorConfig[]): string {
|
||||
return inds.map(i =>
|
||||
`${i.id}|${i.hidden ? '1' : '0'}|${i.lastValueVisible === false ? '0' : '1'}|${(i.plots ?? []).map(p => `${p.color ?? ''}:${p.lineWidth ?? 1}:${p.lineStyle ?? 'solid'}`).join(',')}|${JSON.stringify(i.plotVisibility ?? {})}|${JSON.stringify((i.hlines ?? []).map(h => `${h.price}:${h.color}:${h.visible ?? true}:${h.lineStyle ?? 'dashed'}:${h.lineWidth ?? 1}`))}|${JSON.stringify(i.cloudColors ?? {})}`
|
||||
`${i.id}|${i.hidden ? '1' : '0'}|${i.lastValueVisible === false ? '0' : '1'}|${(i.plots ?? []).map(p => `${p.color ?? ''}:${p.lineWidth ?? 1}:${p.lineStyle ?? 'solid'}:${p.histogramUpColor ?? ''}:${p.histogramDownColor ?? ''}`).join(',')}|${JSON.stringify(i.plotVisibility ?? {})}|${JSON.stringify((i.hlines ?? []).map(h => `${h.price}:${h.color}:${h.visible ?? true}:${h.lineStyle ?? 'dashed'}:${h.lineWidth ?? 1}`))}|${JSON.stringify(i.cloudColors ?? {})}`
|
||||
).join(';');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user