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 D3MouseZone from './D3MouseZone'
|
||||||
import {
|
import {
|
||||||
|
renderArea,
|
||||||
renderLine,
|
renderLine,
|
||||||
renderPoint,
|
renderPoint,
|
||||||
renderNeedle
|
renderNeedle
|
||||||
@ -42,9 +43,9 @@ const defaultOffsets: ChartOffset = {
|
|||||||
right: 10,
|
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')
|
if (typeof accessor === 'function')
|
||||||
return accessor
|
return accessor
|
||||||
return (d) => d[accessor]
|
return (d) => d[accessor]
|
||||||
@ -98,7 +99,6 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
|
|||||||
...other
|
...other
|
||||||
}: D3ChartProps<DataType>) => {
|
}: D3ChartProps<DataType>) => {
|
||||||
const xAxisConfig = usePartialProps<ChartAxis<DataType>>(_xAxisConfig, getDefaultXAxisConfig)
|
const xAxisConfig = usePartialProps<ChartAxis<DataType>>(_xAxisConfig, getDefaultXAxisConfig)
|
||||||
|
|
||||||
const offset = usePartialProps(_offset, defaultOffsets)
|
const offset = usePartialProps(_offset, defaultOffsets)
|
||||||
|
|
||||||
const [svgRef, setSvgRef] = useState<SVGSVGElement | null>(null)
|
const [svgRef, setSvgRef] = useState<SVGSVGElement | null>(null)
|
||||||
@ -285,6 +285,9 @@ const _D3Chart = <DataType extends Record<string, unknown>>({
|
|||||||
case 'point':
|
case 'point':
|
||||||
chartData = renderPoint<DataType>(xAxis, yAxis, chart, chartData)
|
chartData = renderPoint<DataType>(xAxis, yAxis, chart, chartData)
|
||||||
break
|
break
|
||||||
|
case 'area':
|
||||||
|
chartData = renderArea<DataType>(xAxis, yAxis, chart, chartData)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { CSSProperties, memo, ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
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 * as d3 from 'd3'
|
||||||
|
|
||||||
import { isDev } from '@utils'
|
import { isDev } from '@utils'
|
||||||
@ -40,7 +40,7 @@ const makeDefaultRender = <DataType,>(): D3RenderFunction<DataType> => (data, mo
|
|||||||
case 'needle': Icon = BarChartOutlined; break
|
case 'needle': Icon = BarChartOutlined; break
|
||||||
case 'line': Icon = LineChartOutlined; break
|
case 'line': Icon = LineChartOutlined; break
|
||||||
case 'point': Icon = DotChartOutlined; break
|
case 'point': Icon = DotChartOutlined; break
|
||||||
// case 'area': Icon = AreaChartOutlined; break
|
case 'area': Icon = AreaChartOutlined; break
|
||||||
// case 'dot': Icon = DotChartOutLined; break
|
// case 'dot': Icon = DotChartOutLined; break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +110,7 @@ const getTouchedElements = <DataType,>(
|
|||||||
): d3.Selection<any, DataType, any, any> => {
|
): d3.Selection<any, DataType, any, any> => {
|
||||||
let nodes: d3.Selection<any, any, any, any>
|
let nodes: d3.Selection<any, any, any, any>
|
||||||
switch (chart.type) {
|
switch (chart.type) {
|
||||||
|
case 'area':
|
||||||
case 'line':
|
case 'line':
|
||||||
case 'point': {
|
case 'point': {
|
||||||
const tag = chart.point?.shape ?? 'circle'
|
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 './line'
|
||||||
export * from './needle'
|
export * from './needle'
|
||||||
export * from './points'
|
export * from './points'
|
||||||
|
@ -38,6 +38,15 @@ export type BaseChartDataset<DataType> = {
|
|||||||
dash?: string | number | [string | number, string | number]
|
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 = {
|
export type LineChartDataset = {
|
||||||
type: 'line'
|
type: 'line'
|
||||||
nullValues?: 'skip' | 'gap' | 'none'
|
nullValues?: 'skip' | 'gap' | 'none'
|
||||||
@ -49,6 +58,7 @@ export type NeedleChartDataset = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ChartDataset<DataType> = BaseChartDataset<DataType> & (
|
export type ChartDataset<DataType> = BaseChartDataset<DataType> & (
|
||||||
|
AreaChartDataset |
|
||||||
LineChartDataset |
|
LineChartDataset |
|
||||||
NeedleChartDataset |
|
NeedleChartDataset |
|
||||||
PointChartDataset
|
PointChartDataset
|
||||||
|
Loading…
Reference in New Issue
Block a user