Добавлена горизонтальная зона регулятора

This commit is contained in:
goodmice 2022-08-15 12:28:07 +05:00
parent 48ee08acab
commit cf27402810
2 changed files with 51 additions and 25 deletions

View File

@ -602,6 +602,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
height={sizes.chartsHeight} height={sizes.chartsHeight}
left={sizes.inlineWidth + sizes.left} left={sizes.inlineWidth + sizes.left}
top={sizes.chartsTop} top={sizes.chartsTop}
zoneWidth={sizes.inlineWidth}
/> />
<D3MouseZone width={width} height={height} offset={{ ...offset, top: sizes.chartsTop }}> <D3MouseZone width={width} height={height} offset={{ ...offset, top: sizes.chartsTop }}>
<D3HorizontalCursor <D3HorizontalCursor

View File

@ -71,10 +71,11 @@ export type D3MonitoringLimitChartProps<DataType> = {
height: number height: number
left: number left: number
top: number top: number
zoneWidth?: number
} }
const tooltipWidth = 300 const tooltipWidth = 300
const tooltipHeight = 130 const tooltipHeight = 120
const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({ const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({
yAxis, yAxis,
@ -83,17 +84,17 @@ const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({
height, height,
left, left,
top, top,
regulators regulators,
zoneWidth = 0
}: D3MonitoringLimitChartProps<DataType>) => { }: D3MonitoringLimitChartProps<DataType>) => {
const [ref, setRef] = useState<SVGGElement | null>(null) const [ref, setRef] = useState<SVGGElement | null>(null)
const [tooltipRef, setTooltipRef] = useState<SVGForeignObjectElement | null>(null) const [selected, setSelected] = useState<LimitChartData & { x: number, y: number, visible: boolean }>()
const [selected, setSelected] = useState<Partial<LimitChartData & { x: number, y: number, visible: boolean }>>({})
const data = useMemo(() => calcualteData(chartData), [chartData]) const data = useMemo(() => calcualteData(chartData), [chartData])
useEffect(() => { useEffect(() => {
if (!ref || !yAxis) return if (!ref || !yAxis) return
const elms = d3.select(ref).selectAll<SVGRectElement, unknown>('rect').data(data) const elms = d3.select(ref).select('.bars').selectAll<SVGRectElement, unknown>('rect').data(data)
elms.exit().remove() elms.exit().remove()
const newElms = elms.enter().append('rect') const newElms = elms.enter().append('rect')
@ -104,32 +105,56 @@ const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({
.attr('y', (d) => yAxis(d.dateStart)) .attr('y', (d) => yAxis(d.dateStart))
.attr('fill', (d) => regulators[d.id].color) .attr('fill', (d) => regulators[d.id].color)
.on('mouseover', (_, d) => { .on('mouseover', (_, d) => {
const y = (yAxis(d.dateStart) + yAxis(d.dateEnd) - tooltipHeight) / 2 const y = yAxis(d.dateStart) - tooltipHeight
setSelected({ ...d, y, x: -tooltipWidth, visible: true }) setSelected({ ...d, y, x: -tooltipWidth - 10, visible: true })
}) })
.on('mouseout', (_, d) => setSelected((pre) => ({ ...pre, visible: false }))) .on('mouseout', (_, d) => setSelected((pre) => pre ? ({ ...pre, visible: false }) : undefined))
}, [yAxis, data, ref, width]) }, [yAxis, data, ref, width])
const zoneY1 = useMemo(() => yAxis && selected ? yAxis(selected.dateStart) : 0, [yAxis, selected])
const zoneY2 = useMemo(() => yAxis && selected ? yAxis(selected.dateEnd) : 0, [yAxis, selected])
const tooltipStyle = useMemo(() => ({ transition: 'opacity .1s ease-in-out', opacity: selected?.visible ? 1 : 0 }), [selected])
return ( return (
<g transform={`translate(${left}, ${top})`} stroke={'#333'} strokeWidth={1} fill={'none'}> <g transform={`translate(${left}, ${top})`} stroke={'#333'} strokeWidth={1} fill={'none'}>
<g ref={setRef} strokeWidth={0} /> <g ref={setRef} >
<g className={'bars'} strokeWidth={0} />
{selected && (
<g strokeDasharray={'6, 3, 3, 3'} style={tooltipStyle} stroke={regulators[selected.id].color}>
<line x1={-zoneWidth} y1={zoneY1} y2={zoneY1} />
<line x1={-zoneWidth} y1={zoneY2} y2={zoneY2} />
<rect
opacity={0.1}
stroke={'none'}
x={-zoneWidth}
y={zoneY1}
width={zoneWidth}
height={zoneY2 - zoneY1}
fill={regulators[selected.id].color}
/>
</g>
)}
</g>
<rect x={0} y={0} width={width} height={height} /> <rect x={0} y={0} width={width} height={height} />
<foreignObject ref={setTooltipRef} width={tooltipWidth} height={tooltipHeight} x={selected.x ?? 0} y={selected.y ?? 0} pointerEvents={'none'}> {selected && (
<div className={'tooltip right'} style={{ transition: 'opacity .1s ease-in-out', opacity: selected.visible ? 1 : 0 }}> <foreignObject width={tooltipWidth} height={tooltipHeight} x={selected.x} y={selected.y} pointerEvents={'none'}>
<Grid> <div className={'tooltip bottom'} style={tooltipStyle}>
<GridItem row={1} col={1}>Регулятор:</GridItem> <Grid>
<GridItem row={1} col={2}>{selected?.id ? regulators[selected.id].label : '---'}</GridItem> <GridItem row={1} col={1}>Регулятор:</GridItem>
<GridItem row={2} col={1}>Начало:</GridItem> <GridItem row={1} col={2}>{regulators[selected.id].label}</GridItem>
<GridItem row={2} col={2}>{formatDate(selected?.dateStart) ?? '---'}</GridItem> <GridItem row={2} col={1}>Начало:</GridItem>
<GridItem row={2} col={3}>{selected?.depthStart?.toFixed(2) ?? '---'}</GridItem> <GridItem row={2} col={2}>{formatDate(selected.dateStart)}</GridItem>
<GridItem row={2} col={4}>м.</GridItem> <GridItem row={2} col={3}>{selected.depthStart?.toFixed(2) ?? '---'}</GridItem>
<GridItem row={3} col={1}>Конец:</GridItem> <GridItem row={2} col={4}>м.</GridItem>
<GridItem row={3} col={2}>{formatDate(selected?.dateEnd) ?? '---'}</GridItem> <GridItem row={3} col={1}>Конец:</GridItem>
<GridItem row={3} col={3}>{selected?.depthEnd?.toFixed(2) ?? '---'}</GridItem> <GridItem row={3} col={2}>{formatDate(selected.dateEnd)}</GridItem>
<GridItem row={3} col={4}>м.</GridItem> <GridItem row={3} col={3}>{selected.depthEnd?.toFixed(2) ?? '---'}</GridItem>
</Grid> <GridItem row={3} col={4}>м.</GridItem>
</div> </Grid>
</foreignObject> </div>
</foreignObject>
)}
</g> </g>
) )
} }