diff --git a/src/components/d3/D3HorizontalPercentChart.tsx b/src/components/d3/D3HorizontalPercentChart.tsx index 938ab72..18cc6f8 100644 --- a/src/components/d3/D3HorizontalPercentChart.tsx +++ b/src/components/d3/D3HorizontalPercentChart.tsx @@ -20,9 +20,7 @@ export type D3HorizontalChartProps = { height?: Property.Height data: PercentChartDataType[] offset?: Partial - selected?: string | null - onMouseOver?: (e: MouseEvent, d: PercentChartDataType) => void - onMouseOut?: (e: MouseEvent, d: PercentChartDataType) => void + afterDraw?: (d: d3.Selection) => void } const defaultOffset = { top: 50, right: 100, bottom: 50, left: 100 } @@ -32,9 +30,7 @@ export const D3HorizontalPercentChart = memo(({ height: givenHeight = '100%', offset: givenOffset, data, - selected = null, - onMouseOver = () => {}, - onMouseOut= () => {}, + afterDraw, }) => { const offset = usePartialProps(givenOffset, defaultOffset) @@ -51,8 +47,8 @@ export const D3HorizontalPercentChart = memo(({ useEffect(() => { /// Отрисовываем оси X сверху и снизу if (width < 100 || height < 100 || !root) return - const xAxisTop = d3.axisTop(xScale).tickFormat((d) => `${d}%`).tickValues([0, 25, 50, 75, 100]).tickSize(-inlineHeight) - const xAxisBottom = d3.axisBottom(xScale).tickFormat((d) => `${d}%`).tickValues([0, 25, 50, 75, 100]) + const xAxisTop = d3.axisTop(xScale).tickFormat((d) => `${d}%`).ticks(4).tickSize(-inlineHeight) + const xAxisBottom = d3.axisBottom(xScale).tickFormat((d) => `${d}%`).ticks(4) root.selectChild('.axis.x.bottom').call(xAxisBottom) root.selectChild('.axis.x.top').call(xAxisTop) @@ -77,15 +73,13 @@ export const D3HorizontalPercentChart = memo(({ .selectAll('rect') .attr('fill', (d) => d.color || 'black') .attr('y', (d) => yScale(d.name) ?? null) - .attr('stroke', d => selected && d.name === selected ? 'black' : '') - .attr('stroke-width', d => selected && d.name === selected ? '2' : '0') .attr('height', yScale.bandwidth()) - .on('mouseover', onMouseOver) - .on('mouseout', onMouseOut) .transition(delay) .attr('width', (d) => d.percent > 0 ? xScale(d.percent) : 0) - }, [data, width, height, root, yScale, xScale, selected]) + afterDraw?.(root) + + }, [data, width, height, root, yScale, xScale, afterDraw]) return ( diff --git a/src/pages/Telemetry/OperationTime/index.jsx b/src/pages/Telemetry/OperationTime/index.jsx index f71457b..1fd56e9 100644 --- a/src/pages/Telemetry/OperationTime/index.jsx +++ b/src/pages/Telemetry/OperationTime/index.jsx @@ -45,7 +45,7 @@ export const OperationTime = memo(() => { const [showLoader, setShowLoader] = useState(false) const [data, setData] = useState([]) const [selected, setSelected] = useState([]) - const [selectedOnHover, setSelectedOnHover] = useState(null) + const [selectedSubsystem, setSelectedSubsystem] = useState(null) const [dateRange, setDateRange] = useState([]) const [well] = useWell() @@ -63,36 +63,46 @@ export const OperationTime = memo(() => { const onRow = useCallback((item) => { const out = { onMouseEnter: () => { - setSelectedOnHover(item.subsystemName) + setSelectedSubsystem(item.subsystemName) }, onMouseLeave: () => { - setSelectedOnHover(null) + setSelectedSubsystem(null) }, } - if (item.subsystemName === selectedOnHover) { - out.style = { background: '#FAFAFA', fontSize: '16px', fontWeight: '600' } + if (item.subsystemName === selectedSubsystem) { + out.style = { background: '#FAFAFA', fontSize: '16px', fontWeight: '600', transition: 'all 0.2s ease-out' } } return out - }, [selectedOnHover]) + }, [selectedSubsystem]) - const onMouseOver = useCallback(function (e, d) { - setSelectedOnHover(d.name) + const onMouseOver = useCallback((_, d) => { + setSelectedSubsystem(d.name) }, []) - const onMouseOut = useCallback(function (e, d) { - setSelectedOnHover(null) + const onMouseOut = useCallback(() => { + setSelectedSubsystem(null) }, []) + const afterDraw = useCallback(function(selection) { + selection.selectAll('rect') + .on('mouseover', onMouseOver) + .on('mouseout', onMouseOut) + .transition(200) + .style('stroke-width', d => d.name === selectedSubsystem ? '2' : '0') + .style('stroke', d => d.name === selectedSubsystem ? 'black' : '') + .style('stroke-opacity', '0.4') + }, [onMouseOver, onMouseOut, selectedSubsystem]) + useEffect(() => { invokeWebApiWrapperAsync( async () => { if (!well.id) return // Ограничение задаётся только если выбраны обе даты - const startDate = dateRange && dateRange[1] ? dateRange[0]?.toISOString() : undefined - const endDate = dateRange && dateRange[1] ? dateRange[1]?.toISOString() : undefined + const startDate = dateRange?.[1] ? dateRange[0]?.toISOString() : undefined + const endDate = dateRange?.[1] ? dateRange[1]?.toISOString() : undefined const data = await SubsystemOperationTimeService.getStat(well.id, undefined, startDate, endDate) // Выбираем цвета для подсистем (если цветов не хватает начинаем сначала) @@ -132,11 +142,11 @@ export const OperationTime = memo(() => {