Добавлено опциональное подключение анимации для графиков

This commit is contained in:
goodmice 2022-08-04 01:31:35 +05:00
parent 8f9383654d
commit 53c99a5f42
6 changed files with 39 additions and 29 deletions

View File

@ -3,6 +3,8 @@ import * as d3 from 'd3'
import { ChartRegistry } from '@components/d3/types'
import { makePointsOptimizator } from '@utils'
import { appendTransition } from './base'
export const renderArea = <DataType extends Record<string, unknown>>(
xAxis: (value: any) => number,
yAxis: (value: any) => number,
@ -47,10 +49,8 @@ export const renderArea = <DataType extends Record<string, unknown>>(
if (chart().selectAll('path').empty())
chart().append('path')
chart().selectAll('path')
.transition()
.duration(chart.animDurationMs || 0)
.attr('d', area(data as any))
appendTransition(chart().selectAll('path'), chart)
.attr('d', area(data))
.attr('stroke-dasharray', chart.dash ? String(chart.dash) : null)
.attr('fill', chart.areaColor ?? null)

View File

@ -0,0 +1,12 @@
import * as d3 from 'd3'
import { ChartRegistry } from '../types'
export const appendTransition = <DataType, BaseType extends d3.BaseType, Datum, PElement extends d3.BaseType, PDatum>(
elms: d3.Selection<BaseType, Datum, PElement, PDatum>,
chart: ChartRegistry<DataType>
): d3.Selection<BaseType, Datum, PElement, PDatum> => {
if (chart.animDurationMs && chart.animDurationMs > 0)
return elms.transition().duration(chart.animDurationMs) as any
return elms
}

View File

@ -3,6 +3,8 @@ import * as d3 from 'd3'
import { ChartRegistry } from '@components/d3/types'
import { makePointsOptimizator } from '@utils'
import { appendTransition } from './base'
export const renderLine = <DataType extends Record<string, unknown>>(
xAxis: (value: any) => number,
yAxis: (value: any) => number,
@ -35,11 +37,9 @@ export const renderLine = <DataType extends Record<string, unknown>>(
if (chart().selectAll('path').empty())
chart().append('path')
chart().selectAll('path')
.transition()
.duration(chart.animDurationMs ?? 0)
appendTransition(chart().selectAll('path'), chart)
.attr('d', line(data))
.attr('stroke-dasharray', String(chart.dash ?? ''))
.attr('stroke-dasharray', chart.dash ? String(chart.dash) : null)
return data
}

View File

@ -1,5 +1,7 @@
import { ChartOffset, ChartRegistry } from '@components/d3/types'
import { appendTransition } from './base'
export const renderNeedle = <DataType extends Record<string, unknown>>(
xAxis: (value: d3.NumberValue) => number,
yAxis: (value: d3.NumberValue) => number,
@ -19,10 +21,7 @@ export const renderNeedle = <DataType extends Record<string, unknown>>(
currentNeedles.exit().remove()
currentNeedles.enter().append('line')
chart()
.selectAll<SVGLineElement, DataType>('line')
.transition()
.duration(chart.animDurationMs ?? 0)
appendTransition(chart().selectAll<SVGLineElement, DataType>('line'), chart)
.attr('x1', (d) => xAxis(chart.x(d)))
.attr('x2', (d) => xAxis(chart.x(d)))
.attr('y1', height - offset.bottom - offset.top)

View File

@ -1,5 +1,7 @@
import { ChartRegistry, PointChartDataset } from '@components/d3/types'
import { appendTransition } from './base'
const defaultConfig: Required<Omit<PointChartDataset, 'type'>> = {
radius: 3,
shape: 'circle',
@ -10,6 +12,14 @@ const defaultConfig: Required<Omit<PointChartDataset, 'type'>> = {
fillOpacity: 1,
}
const getPointsRoot = <DataType,>(chart: ChartRegistry<DataType>, embeded?: boolean): d3.Selection<SVGGElement, any, any, any> => {
const root = chart()
if (!embeded) return root
if (root.select('.points').empty())
root.append('g').attr('class', 'points')
return root.select('.points')
}
export const renderPoint = <DataType extends Record<string, unknown>>(
xAxis: (value: any) => number,
yAxis: (value: any) => number,
@ -24,19 +34,7 @@ export const renderPoint = <DataType extends Record<string, unknown>>(
config = { ...defaultConfig, ...chart }
else return data
const getPointsRoot = (): d3.Selection<any, any, any, any> => {
let root = chart()
if (embeded) {
if (root.select('.points').empty())
root.append('g').attr('class', 'points')
root = root.select('.points')
}
return root
}
getPointsRoot()
.transition()
.duration(chart.animDurationMs ?? 0)
appendTransition(getPointsRoot(chart, embeded), chart)
.attr('stroke-width', config.strokeWidth)
.attr('fill-opacity', config.fillOpacity)
.attr('fill', config.fillColor)
@ -45,14 +43,14 @@ export const renderPoint = <DataType extends Record<string, unknown>>(
const shape = ['hline', 'vline'].includes(config.shape) ? 'line' : config.shape
const currentPoints = getPointsRoot()
const currentPoints = getPointsRoot(chart, embeded)
.selectAll(shape)
.data(data.filter(chart.y))
currentPoints.exit().remove()
currentPoints.enter().append(shape)
const newPoints = getPointsRoot()
const newPoints = getPointsRoot(chart, embeded)
.selectAll<d3.BaseType, DataType>(shape)
.transition()
.duration(chart.animDurationMs ?? 0)

View File

@ -1,6 +1,8 @@
import { getByAccessor } from '@components/d3/functions'
import { ChartRegistry } from '@components/d3/types'
import { appendTransition } from './base'
export const renderRectArea = <DataType extends Record<string, any>>(
xAxis: (value: d3.NumberValue) => number,
yAxis: (value: d3.NumberValue) => number,
@ -28,8 +30,7 @@ export const renderRectArea = <DataType extends Record<string, any>>(
rects.exit().remove()
rects.enter().append('rect')
const actualRects = chart()
.selectAll<SVGRectElement, Record<string, any>>('rect')
appendTransition(chart().selectAll<SVGRectElement, Record<string, any>>('rect'), chart)
.attr('x1', (d) => xAxis(xMin(d)))
.attr('x2', (d) => xAxis(xMax(d)))
.attr('y1', (d) => yAxis(yMin(d)))