diff --git a/src/features/history-chart/HistoryChartArea.tsx b/src/features/history-chart/HistoryChartArea.tsx index 2649a14..1130542 100644 --- a/src/features/history-chart/HistoryChartArea.tsx +++ b/src/features/history-chart/HistoryChartArea.tsx @@ -1,6 +1,7 @@ import type { EChartsOption } from 'echarts'; import ReactEChartsCore from 'echarts-for-react/esm/core.js'; -import { useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; +import type { WheelEvent } from 'react'; import type { DataZoomEventBatch } from './chartTypes'; import { echarts } from './historyChartEcharts'; @@ -12,6 +13,21 @@ type HistoryChartAreaProps = { onDataZoom: (event: DataZoomEventBatch) => void; }; +/** Включает или выключает нативный X-зум колесом, чтобы Shift + колесо работал только по Y. */ +function setXAxisWheelZoom(chart: ReturnType, enabled: boolean): void { + chart.setOption( + { + dataZoom: [ + { + id: 'history-x-inside', + zoomOnMouseWheel: enabled, + }, + ], + }, + { lazyUpdate: true }, + ); +} + /** Отвечает только за визуальную область графика: placeholder или ECharts canvas. */ export function HistoryChartArea({ hasData, @@ -20,12 +36,55 @@ export function HistoryChartArea({ option, onDataZoom, }: HistoryChartAreaProps) { + const chartRef = useRef | null>(null); + const xWheelZoomEnabledRef = useRef(true); const onChartEvents = useMemo( () => ({ datazoom: onDataZoom, }), [onDataZoom], ); + const updateXAxisWheelZoom = useCallback((enabled: boolean) => { + const chart = chartRef.current?.getEchartsInstance(); + + if (!chart || xWheelZoomEnabledRef.current === enabled) { + return; + } + + xWheelZoomEnabledRef.current = enabled; + setXAxisWheelZoom(chart, enabled); + }, []); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Shift') { + updateXAxisWheelZoom(false); + } + }; + const handleKeyUp = (event: KeyboardEvent) => { + if (event.key === 'Shift') { + updateXAxisWheelZoom(true); + } + }; + const handleBlur = () => updateXAxisWheelZoom(true); + + window.addEventListener('keydown', handleKeyDown); + window.addEventListener('keyup', handleKeyUp); + window.addEventListener('blur', handleBlur); + + return () => { + window.removeEventListener('keydown', handleKeyDown); + window.removeEventListener('keyup', handleKeyUp); + window.removeEventListener('blur', handleBlur); + }; + }, [updateXAxisWheelZoom]); + + const handleWheelCapture = useCallback( + (event: WheelEvent) => { + updateXAxisWheelZoom(!event.shiftKey); + }, + [updateXAxisWheelZoom], + ); if (!hasSelection) { return
Разверните список показателей и выберите серию для графика
; @@ -39,5 +98,16 @@ export function HistoryChartArea({ return
Нет данных для выбранного диапазона
; } - return ; + return ( +
+ +
+ ); } diff --git a/src/styles/charts.css b/src/styles/charts.css index 46f8a77..6b8d3b2 100644 --- a/src/styles/charts.css +++ b/src/styles/charts.css @@ -1,8 +1,14 @@ +.history-chart-shell, .history-chart { width: 100%; height: 440px; } +.history-chart-shell .history-chart { + height: 100%; +} + +.chart-section--archive .history-chart-shell, .chart-section--archive .history-chart { flex: 1; min-height: 520px; @@ -67,6 +73,7 @@ } @media (max-width: 680px) { + .chart-section--archive .history-chart-shell, .chart-section--archive .history-chart, .chart-section--archive .chart-placeholder { min-height: 420px;