차트 세로크로스헤어 교차점 on off
This commit is contained in:
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user