차트 세로크로스헤어 교차점 on off

This commit is contained in:
Macbook
2026-06-22 12:17:03 +09:00
parent 4a3538fb35
commit a1812922a0
13 changed files with 179 additions and 8 deletions
+4
View File
@@ -137,6 +137,7 @@ export interface ChartSlotHandle {
setSeriesPriceLabelsEnabled: (enabled: boolean) => void;
setCandleAreaPriceLabelsEnabled: (enabled: boolean) => void;
setIndicatorAreaPriceLabelsEnabled: (enabled: boolean) => void;
setCrosshairMarkersVisible: (enabled: boolean) => void;
/** 거래량 pane on/off */
setVolumeVisible: (visible: boolean) => void;
/** 9·20일 신고가·신저가 표시 */
@@ -382,6 +383,9 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
setIndicatorAreaPriceLabelsEnabled: (enabled: boolean) => {
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(enabled);
},
setCrosshairMarkersVisible: (enabled: boolean) => {
managerRef.current?.setCrosshairMarkersVisible(enabled);
},
setVolumeVisible: (visible: boolean) => {
managerRef.current?.setVolumeVisible(visible);
},
+23
View File
@@ -129,6 +129,8 @@ interface SettingsPageProps {
onChartLegendOptionsChange?: (patch: Partial<ChartLegendVisibility>) => void;
chartCrosshairInfoVisible?: boolean;
onChartCrosshairInfoVisible?: (v: boolean) => void;
chartCrosshairMarkersVisible?: boolean;
onChartCrosshairMarkersVisible?: (v: boolean) => void;
chartHoverToolbarVisible?: boolean;
onChartHoverToolbarVisible?: (v: boolean) => void;
chartPaneSeparator?: ChartPaneSeparatorOptions;
@@ -1010,6 +1012,8 @@ interface ChartPanelProps {
onChartLegendOptionsChange?: (patch: Partial<ChartLegendVisibility>) => void;
chartCrosshairInfoVisible?: boolean;
onChartCrosshairInfoVisible?: (v: boolean) => void;
chartCrosshairMarkersVisible?: boolean;
onChartCrosshairMarkersVisible?: (v: boolean) => void;
chartHoverToolbarVisible?: boolean;
onChartHoverToolbarVisible?: (v: boolean) => void;
chartPaneSeparator?: ChartPaneSeparatorOptions;
@@ -1036,6 +1040,8 @@ const ChartPanel: React.FC<ChartPanelProps> = ({
onChartLegendOptionsChange,
chartCrosshairInfoVisible = true,
onChartCrosshairInfoVisible,
chartCrosshairMarkersVisible = true,
onChartCrosshairMarkersVisible,
chartHoverToolbarVisible = true,
onChartHoverToolbarVisible,
chartPaneSeparator,
@@ -1248,6 +1254,19 @@ const ChartPanel: React.FC<ChartPanelProps> = ({
<span className="stg-toggle-slider" />
</label>
</SettingRow>
<SettingRow
label="교차점 점 표시"
desc="켜면 세로 크로스헤어가 캔들·보조지표 선과 만나는 위치에 색 점이 표시됩니다. 끄면 크로스헤어 선만 표시됩니다."
>
<label className="stg-toggle">
<input
type="checkbox"
checked={chartCrosshairMarkersVisible}
onChange={e => onChartCrosshairMarkersVisible?.(e.target.checked)}
/>
<span className="stg-toggle-slider" />
</label>
</SettingRow>
</SettingSection>
)}
@@ -1955,6 +1974,8 @@ const SettingsPage: React.FC<SettingsPageProps> = ({
onChartLegendOptionsChange,
chartCrosshairInfoVisible = true,
onChartCrosshairInfoVisible,
chartCrosshairMarkersVisible = true,
onChartCrosshairMarkersVisible,
chartHoverToolbarVisible = true,
onChartHoverToolbarVisible,
chartPaneSeparator,
@@ -2077,6 +2098,8 @@ const SettingsPage: React.FC<SettingsPageProps> = ({
onChartLegendOptionsChange={onChartLegendOptionsChange}
chartCrosshairInfoVisible={chartCrosshairInfoVisible}
onChartCrosshairInfoVisible={onChartCrosshairInfoVisible}
chartCrosshairMarkersVisible={chartCrosshairMarkersVisible}
onChartCrosshairMarkersVisible={onChartCrosshairMarkersVisible}
chartHoverToolbarVisible={chartHoverToolbarVisible}
onChartHoverToolbarVisible={onChartHoverToolbarVisible}
chartPaneSeparator={chartPaneSeparator}
+13
View File
@@ -6,6 +6,7 @@ import { formatUpbitKrwPrice } from '../utils/safeFormat';
import { useChartTimeFormat } from '../utils/chartTimeFormat';
import { setIndicatorChartContext } from '../utils/indicatorRegistry';
import { DISPLAY_COUNT } from '../hooks/useUpbitData';
import { useAppSettings, resolveAppDefaults } from '../hooks/useAppSettings';
/** Upbit 실시간 — 초기 히스토리가 이 개수 미만이면 setData 하지 않음 (종목 전환 직후 sparse 봉 → 캔들 폭 비정상) */
const MIN_BARS_FOR_FULL_RELOAD = Math.min(50, Math.floor(DISPLAY_COUNT / 4));
@@ -165,6 +166,8 @@ interface TradingChartProps {
showCandleOverlayControls?: boolean;
/** 크로스헤어 이동 시 OHLC·보조지표 수치 표시 (기본 true) */
crosshairInfoVisible?: boolean;
/** 세로 크로스헤어와 선 그래프 교차점 점 표시 (미지정 시 전역 차트 설정) */
crosshairMarkersVisible?: boolean;
/** 외부 캔들 데이터 fetch 중 (실시간 차트 초기 로딩) */
dataLoading?: boolean;
/** chartPaintReady 변경 알림 (워크스페이스 전체 로딩 오버레이용) */
@@ -237,6 +240,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
showChartRightToolbar,
showCandleOverlayControls = false,
crosshairInfoVisible = true,
crosshairMarkersVisible,
dataLoading = false,
onChartPaintReadyChange,
defaultCandleOnly = false,
@@ -533,6 +537,10 @@ const TradingChart: React.FC<TradingChartProps> = ({
mgr.setVolumeVisible(volumeVisible, wrapperH > 0 ? wrapperH : undefined);
}, [volumeVisible]);
const { settings } = useAppSettings();
const appDefaults = resolveAppDefaults(settings);
const resolvedCrosshairMarkers = crosshairMarkersVisible ?? appDefaults.chartCrosshairMarkersVisible ?? true;
const resolvedCandlePriceLabels = candleAreaPriceLabelsEnabled ?? seriesPriceLabelsEnabled ?? true;
const resolvedIndicatorPriceLabels = indicatorAreaPriceLabelsEnabled ?? seriesPriceLabelsEnabled ?? true;
@@ -544,6 +552,10 @@ const TradingChart: React.FC<TradingChartProps> = ({
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(resolvedIndicatorPriceLabels);
}, [resolvedIndicatorPriceLabels]);
useEffect(() => {
managerRef.current?.setCrosshairMarkersVisible(resolvedCrosshairMarkers);
}, [resolvedCrosshairMarkers]);
useEffect(() => {
if (!paneSeparatorOptions) return;
managerRef.current?.setPaneSeparatorOptions(paneSeparatorOptions);
@@ -1025,6 +1037,7 @@ const TradingChart: React.FC<TradingChartProps> = ({
}
mgr.setCandleAreaPriceLabelsEnabled(resolvedCandlePriceLabels);
mgr.setIndicatorAreaPriceLabelsEnabled(resolvedIndicatorPriceLabels);
mgr.setCrosshairMarkersVisible(resolvedCrosshairMarkers);
if (paneSeparatorOptions) mgr.setPaneSeparatorOptions(paneSeparatorOptions);
if (auxIndicatorOnlyRef.current) mgr.applyAuxIndicatorOnlyLayout(true);
onManagerReady(mgr);
@@ -8,6 +8,8 @@ interface Props {
indicatorAreaEnabled: boolean;
onCandleAreaChange: (enabled: boolean) => void;
onIndicatorAreaChange: (enabled: boolean) => void;
crosshairMarkersEnabled?: boolean;
onCrosshairMarkersChange?: (enabled: boolean) => void;
className?: string;
}
@@ -16,8 +18,11 @@ const ChartPriceAxisLabelSettings: React.FC<Props> = ({
indicatorAreaEnabled,
onCandleAreaChange,
onIndicatorAreaChange,
crosshairMarkersEnabled = true,
onCrosshairMarkersChange,
className = '',
}) => (
<>
<section className={`seval-price-label-settings${className ? ` ${className}` : ''}`}>
<h3 className="seval-price-label-settings-title"> ·</h3>
<div className="seval-price-label-settings-body">
@@ -68,6 +73,30 @@ const ChartPriceAxisLabelSettings: React.FC<Props> = ({
</div>
</div>
</section>
{onCrosshairMarkersChange && (
<section className={`seval-price-label-settings seval-crosshair-marker-settings${className ? ` ${className}` : ''}`}>
<h3 className="seval-price-label-settings-title"> </h3>
<div className="seval-price-label-settings-body">
<div className="seval-price-label-row">
<div className="seval-price-label-row-text">
<span className="seval-price-label-row-title"> </span>
<span className="seval-price-label-row-desc">
· .
</span>
</div>
<label className="ism-toggle seval-price-label-toggle" title="크로스헤어 교차점 점 표시">
<input
type="checkbox"
checked={crosshairMarkersEnabled}
onChange={e => onCrosshairMarkersChange(e.target.checked)}
/>
<span className="ism-toggle-slider" />
</label>
</div>
</div>
</section>
)}
</>
);
export default ChartPriceAxisLabelSettings;
@@ -99,6 +99,7 @@ const StrategyEvaluationChartSettingsTab: React.FC<Props> = ({
const appDefaults = useMemo(() => resolveAppDefaults(settings), [settings]);
const candlePriceLabels = appDefaults.chartCandleAreaPriceLabels !== false;
const indicatorPriceLabels = appDefaults.chartSeriesPriceLabels !== false;
const crosshairMarkers = appDefaults.chartCrosshairMarkersVisible !== false;
const reloadFromDb = useCallback(() => {
const next: Record<string, IndicatorConfig> = {};
@@ -221,6 +222,8 @@ const StrategyEvaluationChartSettingsTab: React.FC<Props> = ({
indicatorAreaEnabled={indicatorPriceLabels}
onCandleAreaChange={v => saveAppSettings({ chartCandleAreaPriceLabels: v })}
onIndicatorAreaChange={v => saveAppSettings({ chartSeriesPriceLabels: v })}
crosshairMarkersEnabled={crosshairMarkers}
onCrosshairMarkersChange={v => saveAppSettings({ chartCrosshairMarkersVisible: v })}
/>
</div>
</div>