Добавлен зум для графика на странице Операции

This commit is contained in:
ts_salikhov 2022-10-27 10:23:24 +04:00
parent b7317a02d5
commit a924cd0ff1

View File

@ -124,6 +124,7 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
const [xAxisRef, setXAxisRef] = useState<SVGGElement | null>(null) const [xAxisRef, setXAxisRef] = useState<SVGGElement | null>(null)
const [yAxisRef, setYAxisRef] = useState<SVGGElement | null>(null) const [yAxisRef, setYAxisRef] = useState<SVGGElement | null>(null)
const [chartAreaRef, setChartAreaRef] = useState<SVGGElement | null>(null) const [chartAreaRef, setChartAreaRef] = useState<SVGGElement | null>(null)
const [currentZoomState, setCurrentZoomState] = useState<d3.ZoomTransform | null>(null)
const xAxisArea = useCallback(() => d3.select(xAxisRef), [xAxisRef]) const xAxisArea = useCallback(() => d3.select(xAxisRef), [xAxisRef])
const yAxisArea = useCallback(() => d3.select(yAxisRef), [yAxisRef]) const yAxisArea = useCallback(() => d3.select(yAxisRef), [yAxisRef])
@ -159,8 +160,13 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
xAxis.domain([domain?.x?.min ?? minX, domain?.x?.max ?? maxX]) xAxis.domain([domain?.x?.min ?? minX, domain?.x?.max ?? maxX])
} }
if (currentZoomState) {
const newXScale = currentZoomState.rescaleX(xAxis)
xAxis.domain(newXScale.domain())
}
return xAxis return xAxis
}, [xAxisConfig, data, domain, width, offset]) }, [xAxisConfig, data, domain, width, offset, currentZoomState])
const yAxis = useMemo(() => { const yAxis = useMemo(() => {
if (!data) return if (!data) return
@ -200,8 +206,13 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
yAxis.range([height - offset.top - offset.bottom, 0]) yAxis.range([height - offset.top - offset.bottom, 0])
if (currentZoomState) {
const newYScale = currentZoomState.rescaleY(yAxis)
yAxis.domain(newYScale.domain())
}
return yAxis return yAxis
}, [charts, data, domain, height, offset]) }, [charts, data, domain, height, offset, currentZoomState])
const nTicks = { const nTicks = {
color: 'lightgray', color: 'lightgray',
@ -348,6 +359,19 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
redrawCharts() redrawCharts()
}, [redrawCharts]) }, [redrawCharts])
useEffect(() => {
if (!svgRef) return
const zoom = d3.zoom<SVGSVGElement, unknown>()
.scaleExtent([1, 5])
.translateExtent([[0, 0], [width, height]])
.on('zoom', () => {
const zoomState = d3.zoomTransform(svgRef)
setCurrentZoomState(zoomState)
})
d3.select(svgRef).call(zoom)
}, [svgRef, width, height, offset])
return ( return (
<LoaderPortal <LoaderPortal
show={loading} show={loading}
@ -366,7 +390,17 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
<svg ref={setSvgRef} width={'100%'} height={'100%'}> <svg ref={setSvgRef} width={'100%'} height={'100%'}>
<g ref={setXAxisRef} className={'axis x'} transform={`translate(${offset.left}, ${height - offset.bottom})`} /> <g ref={setXAxisRef} className={'axis x'} transform={`translate(${offset.left}, ${height - offset.bottom})`} />
<g ref={setYAxisRef} className={'axis y'} transform={`translate(${offset.left}, ${offset.top})`} /> <g ref={setYAxisRef} className={'axis y'} transform={`translate(${offset.left}, ${offset.top})`} />
<g ref={setChartAreaRef} className={'chart-area'} transform={`translate(${offset.left}, ${offset.top})`}> <defs>
<clipPath id={'clipPath'}>
<rect
x={0}
y={0}
width={Math.max(width - offset.left - offset.right, 0)}
height={Math.max(height - offset.top - offset.bottom, 0)}
/>
</clipPath>
</defs>
<g clipPath={'url(#clipPath)'} ref={setChartAreaRef} className={'chart-area'} transform={`translate(${offset.left}, ${offset.top})`}>
<rect <rect
width={Math.max(width - offset.left - offset.right, 0)} width={Math.max(width - offset.left - offset.right, 0)}
height={Math.max(height - offset.top - offset.bottom, 0)} height={Math.max(height - offset.top - offset.bottom, 0)}