На странице Наработка добавлен сброс даты и выделение данных при наведении

This commit is contained in:
ts_salikhov 2022-10-11 01:27:27 +04:00
parent bbf15c1f35
commit 1b23ee3437
2 changed files with 30 additions and 26 deletions

View File

@ -20,9 +20,7 @@ export type D3HorizontalChartProps = {
height?: Property.Height height?: Property.Height
data: PercentChartDataType[] data: PercentChartDataType[]
offset?: Partial<ChartOffset> offset?: Partial<ChartOffset>
selected?: string | null afterDraw?: (d: d3.Selection<SVGGElement, unknown, null, undefined>) => void
onMouseOver?: (e: MouseEvent, d: PercentChartDataType) => void
onMouseOut?: (e: MouseEvent, d: PercentChartDataType) => void
} }
const defaultOffset = { top: 50, right: 100, bottom: 50, left: 100 } const defaultOffset = { top: 50, right: 100, bottom: 50, left: 100 }
@ -32,9 +30,7 @@ export const D3HorizontalPercentChart = memo<D3HorizontalChartProps>(({
height: givenHeight = '100%', height: givenHeight = '100%',
offset: givenOffset, offset: givenOffset,
data, data,
selected = null, afterDraw,
onMouseOver = () => {},
onMouseOut= () => {},
}) => { }) => {
const offset = usePartialProps<ChartOffset>(givenOffset, defaultOffset) const offset = usePartialProps<ChartOffset>(givenOffset, defaultOffset)
@ -51,8 +47,8 @@ export const D3HorizontalPercentChart = memo<D3HorizontalChartProps>(({
useEffect(() => { /// Отрисовываем оси X сверху и снизу useEffect(() => { /// Отрисовываем оси X сверху и снизу
if (width < 100 || height < 100 || !root) return if (width < 100 || height < 100 || !root) return
const xAxisTop = d3.axisTop(xScale).tickFormat((d) => `${d}%`).tickValues([0, 25, 50, 75, 100]).tickSize(-inlineHeight) const xAxisTop = d3.axisTop(xScale).tickFormat((d) => `${d}%`).ticks(4).tickSize(-inlineHeight)
const xAxisBottom = d3.axisBottom(xScale).tickFormat((d) => `${d}%`).tickValues([0, 25, 50, 75, 100]) const xAxisBottom = d3.axisBottom(xScale).tickFormat((d) => `${d}%`).ticks(4)
root.selectChild<SVGGElement>('.axis.x.bottom').call(xAxisBottom) root.selectChild<SVGGElement>('.axis.x.bottom').call(xAxisBottom)
root.selectChild<SVGGElement>('.axis.x.top').call(xAxisTop) root.selectChild<SVGGElement>('.axis.x.top').call(xAxisTop)
@ -77,15 +73,13 @@ export const D3HorizontalPercentChart = memo<D3HorizontalChartProps>(({
.selectAll<SVGRectElement, PercentChartDataType>('rect') .selectAll<SVGRectElement, PercentChartDataType>('rect')
.attr('fill', (d) => d.color || 'black') .attr('fill', (d) => d.color || 'black')
.attr('y', (d) => yScale(d.name) ?? null) .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()) .attr('height', yScale.bandwidth())
.on('mouseover', onMouseOver)
.on('mouseout', onMouseOut)
.transition(delay) .transition(delay)
.attr('width', (d) => d.percent > 0 ? xScale(d.percent) : 0) .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 ( return (
<LoaderPortal show={false} style={{ width: givenWidth, height: givenHeight }}> <LoaderPortal show={false} style={{ width: givenWidth, height: givenHeight }}>

View File

@ -45,7 +45,7 @@ export const OperationTime = memo(() => {
const [showLoader, setShowLoader] = useState(false) const [showLoader, setShowLoader] = useState(false)
const [data, setData] = useState([]) const [data, setData] = useState([])
const [selected, setSelected] = useState([]) const [selected, setSelected] = useState([])
const [selectedOnHover, setSelectedOnHover] = useState(null) const [selectedSubsystem, setSelectedSubsystem] = useState(null)
const [dateRange, setDateRange] = useState([]) const [dateRange, setDateRange] = useState([])
const [well] = useWell() const [well] = useWell()
@ -63,36 +63,46 @@ export const OperationTime = memo(() => {
const onRow = useCallback((item) => { const onRow = useCallback((item) => {
const out = { const out = {
onMouseEnter: () => { onMouseEnter: () => {
setSelectedOnHover(item.subsystemName) setSelectedSubsystem(item.subsystemName)
}, },
onMouseLeave: () => { onMouseLeave: () => {
setSelectedOnHover(null) setSelectedSubsystem(null)
}, },
} }
if (item.subsystemName === selectedOnHover) { if (item.subsystemName === selectedSubsystem) {
out.style = { background: '#FAFAFA', fontSize: '16px', fontWeight: '600' } out.style = { background: '#FAFAFA', fontSize: '16px', fontWeight: '600', transition: 'all 0.2s ease-out' }
} }
return out return out
}, [selectedOnHover]) }, [selectedSubsystem])
const onMouseOver = useCallback(function (e, d) { const onMouseOver = useCallback((_, d) => {
setSelectedOnHover(d.name) setSelectedSubsystem(d.name)
}, []) }, [])
const onMouseOut = useCallback(function (e, d) { const onMouseOut = useCallback(() => {
setSelectedOnHover(null) 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(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
if (!well.id) return if (!well.id) return
// Ограничение задаётся только если выбраны обе даты // Ограничение задаётся только если выбраны обе даты
const startDate = dateRange && dateRange[1] ? dateRange[0]?.toISOString() : undefined const startDate = dateRange?.[1] ? dateRange[0]?.toISOString() : undefined
const endDate = dateRange && dateRange[1] ? dateRange[1]?.toISOString() : undefined const endDate = dateRange?.[1] ? dateRange[1]?.toISOString() : undefined
const data = await SubsystemOperationTimeService.getStat(well.id, undefined, startDate, endDate) const data = await SubsystemOperationTimeService.getStat(well.id, undefined, startDate, endDate)
// Выбираем цвета для подсистем (если цветов не хватает начинаем сначала) // Выбираем цвета для подсистем (если цветов не хватает начинаем сначала)
@ -132,11 +142,11 @@ export const OperationTime = memo(() => {
<D3HorizontalPercentChart <D3HorizontalPercentChart
data={chartData} data={chartData}
colors={subsystemColors} colors={subsystemColors}
selected={selectedOnHover}
width={'100%'} width={'100%'}
height={'50vh'} height={'50vh'}
onMouseOver={onMouseOver} onMouseOver={onMouseOver}
onMouseOut={onMouseOut} onMouseOut={onMouseOut}
afterDraw={afterDraw}
/> />
<Table <Table
bordered bordered