forked from ddrilling/asb_cloud_front
Добавлен Area график
This commit is contained in:
parent
cd3c873368
commit
1402e6ce67
@ -9,6 +9,7 @@ import { isDev, usePartialProps } from '@utils'
|
||||
|
||||
import D3MouseZone from './D3MouseZone'
|
||||
import {
|
||||
renderArea,
|
||||
renderLine,
|
||||
renderPoint,
|
||||
renderNeedle
|
||||
@ -42,9 +43,9 @@ const defaultOffsets: ChartOffset = {
|
||||
right: 10,
|
||||
}
|
||||
|
||||
const getGroupClass = (key: string | number) => `chart-id-${key}`
|
||||
export const getGroupClass = (key: string | number) => `chart-id-${key}`
|
||||
|
||||
const getByAccessor = <DataType extends Record<any, any>, R>(accessor: keyof DataType | ((d: DataType) => R)): ((d: DataType) => R) => {
|
||||
export const getByAccessor = <DataType extends Record<any, any>, R>(accessor: keyof DataType | ((d: DataType) => R)): ((d: DataType) => R) => {
|
||||
if (typeof accessor === 'function')
|
||||
return accessor
|
||||
return (d) => d[accessor]
|
||||
@ -98,7 +99,6 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
|
||||
...other
|
||||
}: D3ChartProps<DataType>) => {
|
||||
const xAxisConfig = usePartialProps<ChartAxis<DataType>>(_xAxisConfig, getDefaultXAxisConfig)
|
||||
|
||||
const offset = usePartialProps(_offset, defaultOffsets)
|
||||
|
||||
const [svgRef, setSvgRef] = useState<SVGSVGElement | null>(null)
|
||||
@ -285,6 +285,9 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
|
||||
case 'point':
|
||||
chartData = renderPoint<DataType>(xAxis, yAxis, chart, chartData)
|
||||
break
|
||||
case 'area':
|
||||
chartData = renderArea<DataType>(xAxis, yAxis, chart, chartData)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { CSSProperties, memo, ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { BarChartOutlined, DotChartOutlined, LineChartOutlined } from '@ant-design/icons'
|
||||
import { AreaChartOutlined, BarChartOutlined, DotChartOutlined, LineChartOutlined } from '@ant-design/icons'
|
||||
import * as d3 from 'd3'
|
||||
|
||||
import { isDev } from '@utils'
|
||||
@ -40,7 +40,7 @@ const makeDefaultRender = <DataType,>(): D3RenderFunction<DataType> => (data, mo
|
||||
case 'needle': Icon = BarChartOutlined; break
|
||||
case 'line': Icon = LineChartOutlined; break
|
||||
case 'point': Icon = DotChartOutlined; break
|
||||
// case 'area': Icon = AreaChartOutlined; break
|
||||
case 'area': Icon = AreaChartOutlined; break
|
||||
// case 'dot': Icon = DotChartOutLined; break
|
||||
}
|
||||
|
||||
@ -110,6 +110,7 @@ const getTouchedElements = <DataType,>(
|
||||
): d3.Selection<any, DataType, any, any> => {
|
||||
let nodes: d3.Selection<any, any, any, any>
|
||||
switch (chart.type) {
|
||||
case 'area':
|
||||
case 'line':
|
||||
case 'point': {
|
||||
const tag = chart.point?.shape ?? 'circle'
|
||||
|
57
src/components/d3/renders/area.ts
Normal file
57
src/components/d3/renders/area.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import * as d3 from 'd3'
|
||||
|
||||
import { ChartRegistry } from '@components/d3/types'
|
||||
import { makePointsOptimizator } from '@utils'
|
||||
|
||||
export const renderArea = <DataType extends Record<string, unknown>>(
|
||||
xAxis: (value: any) => number,
|
||||
yAxis: (value: any) => number,
|
||||
chart: ChartRegistry<DataType>,
|
||||
data: DataType[]
|
||||
): DataType[] => {
|
||||
if (chart.type !== 'area') return data
|
||||
|
||||
let area = d3.area()
|
||||
|
||||
if (chart.y0) {
|
||||
area = area.y0(chart.y0)
|
||||
.y1(d => yAxis(chart.y(d)))
|
||||
} else {
|
||||
area = area.y(d => yAxis(chart.y(d)))
|
||||
}
|
||||
|
||||
if (chart.x0) {
|
||||
area = area.x0(chart.x0)
|
||||
.x1(d => xAxis(chart.x(d)))
|
||||
} else {
|
||||
area = area.x(d => xAxis(chart.x(d)))
|
||||
}
|
||||
|
||||
switch (chart.nullValues || 'skip') {
|
||||
case 'gap':
|
||||
area = area.defined(d => (chart.y(d) ?? null) !== null && !Number.isNaN(chart.y(d)))
|
||||
break
|
||||
case 'skip':
|
||||
data = data.filter(chart.y)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (chart.optimization) {
|
||||
const optimize = makePointsOptimizator<DataType>((a, b) => chart.y(a) === chart.y(b))
|
||||
data = optimize(data)
|
||||
}
|
||||
|
||||
|
||||
if (chart().selectAll('path').empty())
|
||||
chart().append('path')
|
||||
|
||||
chart().selectAll('path')
|
||||
.transition()
|
||||
.duration(chart.animDurationMs || 0)
|
||||
.attr('d', area(data as any))
|
||||
.attr('stroke-dasharray', chart.dash ? String(chart.dash) : null)
|
||||
|
||||
return data
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export * from './area'
|
||||
export * from './line'
|
||||
export * from './needle'
|
||||
export * from './points'
|
||||
|
@ -38,6 +38,15 @@ export type BaseChartDataset<DataType> = {
|
||||
dash?: string | number | [string | number, string | number]
|
||||
}
|
||||
|
||||
export type AreaChartDataset = {
|
||||
type: 'area'
|
||||
x0?: number
|
||||
y0?: number
|
||||
areaColor?: Property.Color
|
||||
nullValues?: 'skip' | 'gap' | 'none'
|
||||
optimization?: boolean
|
||||
}
|
||||
|
||||
export type LineChartDataset = {
|
||||
type: 'line'
|
||||
nullValues?: 'skip' | 'gap' | 'none'
|
||||
@ -49,6 +58,7 @@ export type NeedleChartDataset = {
|
||||
}
|
||||
|
||||
export type ChartDataset<DataType> = BaseChartDataset<DataType> & (
|
||||
AreaChartDataset |
|
||||
LineChartDataset |
|
||||
NeedleChartDataset |
|
||||
PointChartDataset
|
||||
|
Loading…
Reference in New Issue
Block a user