Добавлен тултип для колонки

This commit is contained in:
goodmice 2022-08-15 11:58:32 +05:00
parent cc37bccacf
commit 48ee08acab
3 changed files with 63 additions and 16 deletions

View File

@ -78,12 +78,11 @@ const defaultOffsets: ChartOffset = {
}
const defaultRegulators: TelemetryRegulators = {
1: { color: '#007070', label: 'Расход' },
2: { color: '#59B359', label: 'Скорость блока' },
3: { color: '#FF0000', label: 'Давление' },
4: { color: '#0000CC', label: 'Осевая нагрузка' },
5: { color: '#00B3B3', label: 'Вес на крюке' },
6: { color: '#990099', label: 'Момент на роторе' },
1: { color: '#59B359', label: 'Скорость блока' },
2: { color: '#FF0000', label: 'Давление' },
3: { color: '#0000CC', label: 'Осевая нагрузка' },
4: { color: '#990099', label: 'Момент на роторе' },
5: { color: '#007070', label: 'Расход' },
}
const getDefaultYAxisConfig = <DataType,>(): ChartAxis<DataType> => ({
@ -321,11 +320,12 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
let sets = chartName ? await UserSettingsService.get(chartName) : null
if (typeof sets === 'string')
sets = JSON.parse(sets)
const { settings, regulators } = sets
if (regulators)
setRegulators(regulators)
if (Array.isArray(settings)) {
setDatasets(settings)
if (sets && Array.isArray(sets.settings)) {
if (sets.regulators)
setRegulators(sets.regulators)
if (Array.isArray(sets.settings)) {
setDatasets(sets.settings)
}
} else if (Array.isArray(datasetGroups)) {
setDatasets(datasetGroups)
if (chartName) {

View File

@ -1,18 +1,24 @@
import { memo, useEffect, useMemo, useState } from 'react'
import * as d3 from 'd3'
import { Grid, GridItem } from '@components/Grid'
import { TelemetryDataSaubDto } from '@api'
import { formatDate } from '@utils'
type LimitChartData = {
id: number
dateStart: Date
dateEnd: Date
depthStart: number | null
depthEnd: number | null
}
type LimitChartDataRaw = {
id?: number
dateStart?: string
dateEnd?: string
depthStart?: number | null
depthEnd?: number | null
}
export type TelemetryRegulators = Record<number, {
@ -31,12 +37,17 @@ const calcualteData = <DataType extends TelemetryDataSaubDto>(data: DataType[])
if (last.id === row.idFeedRegulator) {
if (!row.idFeedRegulator) return out
last.dateEnd = row.dateTime
last.depthEnd = row.wellDepth
} else {
const n: LimitChartDataRaw = {}
let n: LimitChartDataRaw = {}
if (row.idFeedRegulator) {
n.id = row.idFeedRegulator
n.dateStart = row.dateTime
n.dateEnd = row.dateTime
n = {
id: row.idFeedRegulator,
dateStart: row.dateTime,
dateEnd: row.dateTime,
depthStart: row.wellDepth,
depthEnd: row.wellDepth,
}
}
out.push(n)
}
@ -47,6 +58,8 @@ const calcualteData = <DataType extends TelemetryDataSaubDto>(data: DataType[])
id: row.id,
dateStart: new Date(row.dateStart),
dateEnd: new Date(row.dateEnd),
depthStart: row.depthStart,
depthEnd: row.depthEnd,
}))
}
@ -60,6 +73,9 @@ export type D3MonitoringLimitChartProps<DataType> = {
top: number
}
const tooltipWidth = 300
const tooltipHeight = 130
const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({
yAxis,
data: chartData,
@ -70,6 +86,8 @@ const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({
regulators
}: D3MonitoringLimitChartProps<DataType>) => {
const [ref, setRef] = useState<SVGGElement | null>(null)
const [tooltipRef, setTooltipRef] = useState<SVGForeignObjectElement | null>(null)
const [selected, setSelected] = useState<Partial<LimitChartData & { x: number, y: number, visible: boolean }>>({})
const data = useMemo(() => calcualteData(chartData), [chartData])
@ -85,12 +103,33 @@ const _D3MonitoringLimitChart = <DataType extends TelemetryDataSaubDto>({
.attr('height', (d) => Math.max(yAxis(d.dateEnd) - yAxis(d.dateStart), 1))
.attr('y', (d) => yAxis(d.dateStart))
.attr('fill', (d) => regulators[d.id].color)
.on('mouseover', (_, d) => {
const y = (yAxis(d.dateStart) + yAxis(d.dateEnd) - tooltipHeight) / 2
setSelected({ ...d, y, x: -tooltipWidth, visible: true })
})
.on('mouseout', (_, d) => setSelected((pre) => ({ ...pre, visible: false })))
}, [yAxis, data, ref, width])
return (
<g transform={`translate(${left}, ${top})`} stroke={'#333'} strokeWidth={1} fill={'none'}>
<g ref={setRef} strokeWidth={0} />
<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'}>
<div className={'tooltip right'} style={{ transition: 'opacity .1s ease-in-out', opacity: selected.visible ? 1 : 0 }}>
<Grid>
<GridItem row={1} col={1}>Регулятор:</GridItem>
<GridItem row={1} col={2}>{selected?.id ? regulators[selected.id].label : '---'}</GridItem>
<GridItem row={2} col={1}>Начало:</GridItem>
<GridItem row={2} col={2}>{formatDate(selected?.dateStart) ?? '---'}</GridItem>
<GridItem row={2} col={3}>{selected?.depthStart?.toFixed(2) ?? '---'}</GridItem>
<GridItem row={2} col={4}>м.</GridItem>
<GridItem row={3} col={1}>Конец:</GridItem>
<GridItem row={3} col={2}>{formatDate(selected?.dateEnd) ?? '---'}</GridItem>
<GridItem row={3} col={3}>{selected?.depthEnd?.toFixed(2) ?? '---'}</GridItem>
<GridItem row={3} col={4}>м.</GridItem>
</Grid>
</div>
</foreignObject>
</g>
)
}

View File

@ -8,7 +8,7 @@
@arrow-size: 8px;
width: 100%;
height: 100% - @arrow-size;
height: 100%;
font-size: 13px;
color: @color;
@ -30,6 +30,7 @@
&.top {
margin-top: @arrow-size;
height: 100% - @arrow-size;
&::after {
border-bottom-color: @bg-color;
@ -42,6 +43,7 @@
&.bottom {
margin-bottom: @arrow-size;
height: 100% - @arrow-size;
&::after {
border-top-color: @bg-color;
@ -53,8 +55,11 @@
&.left {
margin-left: @arrow-size;
width: 100% - @arrow-size;
&::after {
border-right-color: @bg-color;
margin-top: -@arrow-size;
top: 50%;
right: 100%;
}
@ -62,8 +67,11 @@
&.right {
margin-right: @arrow-size;
width: 100% - @arrow-size;
&::after {
border-left-color: @bg-color;
margin-top: -@arrow-size;
top: 50%;
left: 100%;
}