|
1 | 1 | import { Group as KonvaGroup } from 'konva'; |
2 | 2 | import React from 'react'; |
3 | 3 | import { Circle, Group, Path } from 'react-konva'; |
4 | | -import { animated, Spring } from 'react-spring/renderprops-konva.cjs'; |
5 | 4 | import { LegendItem } from '../../chart_types/xy_chart/legend/legend'; |
6 | | -import { AreaGeometry, getGeometryStyle, PointGeometry } from '../../chart_types/xy_chart/rendering/rendering'; |
| 5 | +import { |
| 6 | + AreaGeometry, |
| 7 | + getGeometryStyle, |
| 8 | + PointGeometry, |
| 9 | + getGeometryIdKey, |
| 10 | + GeometryId, |
| 11 | +} from '../../chart_types/xy_chart/rendering/rendering'; |
7 | 12 | import { SharedGeometryStyle } from '../../utils/themes/theme'; |
8 | 13 | import { |
9 | 14 | buildAreaRenderProps, |
@@ -38,110 +43,118 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps, |
38 | 43 | return ( |
39 | 44 | <Group ref={this.barSeriesRef} key={'bar_series'}> |
40 | 45 | {this.renderAreaGeoms()} |
41 | | - {this.renderAreaLines()} |
42 | | - {this.renderAreaPoints()} |
43 | 46 | </Group> |
44 | 47 | ); |
45 | 48 | } |
46 | | - private renderAreaPoints = (): JSX.Element[] => { |
47 | | - const { areas } = this.props; |
48 | | - return areas.reduce( |
49 | | - (acc, glyph, i) => { |
50 | | - const { points, seriesPointStyle, color } = glyph; |
51 | | - |
52 | | - if (!seriesPointStyle.visible) { |
53 | | - return acc; |
| 49 | + private renderAreaGeoms = (): JSX.Element[] => { |
| 50 | + const { sharedStyle, highlightedLegendItem } = this.props; |
| 51 | + const areas = this.props.areas.reduce<{ |
| 52 | + stacked: AreaGeometry[]; |
| 53 | + nonStacked: AreaGeometry[]; |
| 54 | + }>( |
| 55 | + (acc, area) => { |
| 56 | + if (area.isStacked) { |
| 57 | + acc.stacked.push(area); |
| 58 | + } else { |
| 59 | + acc.nonStacked.push(area); |
54 | 60 | } |
55 | | - |
56 | | - const pointStyleProps = buildPointStyleProps(color, seriesPointStyle); |
57 | | - |
58 | | - return [...acc, ...this.renderPoints(points, i, pointStyleProps)]; |
| 61 | + return acc; |
59 | 62 | }, |
60 | | - [] as JSX.Element[], |
| 63 | + |
| 64 | + { stacked: [], nonStacked: [] }, |
61 | 65 | ); |
| 66 | + |
| 67 | + return [ |
| 68 | + ...this.renderStackedAreas(areas.stacked, sharedStyle, highlightedLegendItem), |
| 69 | + ...this.renderNonStackedAreas(areas.nonStacked, sharedStyle, highlightedLegendItem), |
| 70 | + ]; |
62 | 71 | }; |
63 | | - private renderPoints = ( |
64 | | - areaPoints: PointGeometry[], |
65 | | - areaIndex: number, |
66 | | - pointStyleProps: PointStyleProps, |
| 72 | + renderStackedAreas = ( |
| 73 | + areas: AreaGeometry[], |
| 74 | + sharedStyle: SharedGeometryStyle, |
| 75 | + highlightedLegendItem: LegendItem | null, |
67 | 76 | ): JSX.Element[] => { |
68 | | - const areaPointElements: JSX.Element[] = []; |
69 | | - |
70 | | - areaPoints.forEach((areaPoint, pointIndex) => { |
71 | | - const { x, y, transform } = areaPoint; |
72 | | - const key = `area-point-${areaIndex}-${pointIndex}`; |
73 | | - |
74 | | - if (this.props.animated) { |
75 | | - areaPointElements.push( |
76 | | - <Group key={`area-point-group-${areaIndex}-${pointIndex}`} x={transform.x}> |
77 | | - <Spring native from={{ y }} to={{ y }}> |
78 | | - {() => { |
79 | | - const pointProps = buildPointRenderProps(x, y, pointStyleProps); |
80 | | - return <animated.Circle {...pointProps} key={key} />; |
81 | | - }} |
82 | | - </Spring> |
83 | | - </Group>, |
84 | | - ); |
85 | | - } else { |
86 | | - const pointProps = buildPointRenderProps(transform.x + x, y, pointStyleProps); |
87 | | - areaPointElements.push(<Circle {...pointProps} key={key} />); |
| 77 | + const elements: JSX.Element[] = []; |
| 78 | + areas.forEach((glyph) => { |
| 79 | + const { seriesAreaStyle } = glyph; |
| 80 | + if (seriesAreaStyle.visible) { |
| 81 | + elements.push(this.renderArea(glyph, sharedStyle, highlightedLegendItem)); |
88 | 82 | } |
89 | 83 | }); |
90 | | - return areaPointElements; |
91 | | - }; |
92 | | - |
93 | | - private renderAreaGeoms = (): JSX.Element[] => { |
94 | | - const { areas, sharedStyle } = this.props; |
95 | | - const areasToRender: JSX.Element[] = []; |
96 | | - |
97 | 84 | areas.forEach((glyph, i) => { |
98 | | - const { area, color, transform, geometryId, seriesAreaStyle } = glyph; |
99 | | - if (!seriesAreaStyle.visible) { |
100 | | - return; |
| 85 | + const { seriesAreaLineStyle } = glyph; |
| 86 | + if (seriesAreaLineStyle.visible) { |
| 87 | + elements.push(...this.renderAreaLines(glyph, i, sharedStyle, highlightedLegendItem)); |
101 | 88 | } |
102 | | - const customOpacity = seriesAreaStyle ? seriesAreaStyle.opacity : undefined; |
103 | | - const geometryStyle = getGeometryStyle(geometryId, this.props.highlightedLegendItem, sharedStyle, customOpacity); |
104 | | - const key = `area-${i}`; |
105 | | - if (this.props.animated) { |
106 | | - areasToRender.push( |
107 | | - <Group key={`area-group-${i}`} x={transform.x}> |
108 | | - <Spring native from={{ area }} to={{ area }}> |
109 | | - {(props: { area: string }) => { |
110 | | - const areaProps = buildAreaRenderProps(0, props.area, color, seriesAreaStyle, geometryStyle); |
111 | | - return <animated.Path {...areaProps} key={key} />; |
112 | | - }} |
113 | | - </Spring> |
114 | | - </Group>, |
115 | | - ); |
116 | | - } else { |
117 | | - const areaProps = buildAreaRenderProps(transform.x, area, color, seriesAreaStyle, geometryStyle); |
118 | | - areasToRender.push(<Path {...areaProps} key={key} />); |
| 89 | + }); |
| 90 | + areas.forEach((glyph, i) => { |
| 91 | + const { seriesPointStyle } = glyph; |
| 92 | + if (seriesPointStyle.visible) { |
| 93 | + const pointStyleProps = buildPointStyleProps(glyph.color, seriesPointStyle); |
| 94 | + elements.push(...this.renderPoints(glyph.points, i, pointStyleProps, glyph.geometryId)); |
119 | 95 | } |
120 | 96 | }); |
121 | | - return areasToRender; |
| 97 | + return elements; |
122 | 98 | }; |
123 | | - private renderAreaLines = (): JSX.Element[] => { |
124 | | - const { areas, sharedStyle } = this.props; |
125 | | - const linesToRender: JSX.Element[] = []; |
126 | | - areas.forEach((glyph, areaIndex) => { |
127 | | - const { lines, color, geometryId, transform, seriesAreaLineStyle } = glyph; |
128 | | - if (!seriesAreaLineStyle.visible) { |
129 | | - return; |
| 99 | + renderNonStackedAreas = ( |
| 100 | + areas: AreaGeometry[], |
| 101 | + sharedStyle: SharedGeometryStyle, |
| 102 | + highlightedLegendItem: LegendItem | null, |
| 103 | + ): JSX.Element[] => { |
| 104 | + return areas.reduce<JSX.Element[]>((acc, glyph, i) => { |
| 105 | + const { seriesAreaLineStyle, seriesAreaStyle, seriesPointStyle } = glyph; |
| 106 | + if (seriesAreaStyle.visible) { |
| 107 | + acc.push(this.renderArea(glyph, sharedStyle, highlightedLegendItem)); |
| 108 | + } |
| 109 | + if (seriesAreaLineStyle.visible) { |
| 110 | + acc.push(...this.renderAreaLines(glyph, i, sharedStyle, highlightedLegendItem)); |
| 111 | + } |
| 112 | + if (seriesPointStyle.visible) { |
| 113 | + const pointStyleProps = buildPointStyleProps(glyph.color, seriesPointStyle); |
| 114 | + acc.push(...this.renderPoints(glyph.points, i, pointStyleProps, glyph.geometryId)); |
130 | 115 | } |
| 116 | + return acc; |
| 117 | + }, []); |
| 118 | + }; |
| 119 | + private renderArea = ( |
| 120 | + glyph: AreaGeometry, |
| 121 | + sharedStyle: SharedGeometryStyle, |
| 122 | + highlightedLegendItem: LegendItem | null, |
| 123 | + ): JSX.Element => { |
| 124 | + const { area, color, transform, geometryId, seriesAreaStyle } = glyph; |
| 125 | + const customOpacity = seriesAreaStyle ? seriesAreaStyle.opacity : undefined; |
| 126 | + const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle, customOpacity); |
| 127 | + const key = getGeometryIdKey(geometryId, 'area-'); |
| 128 | + const areaProps = buildAreaRenderProps(transform.x, area, color, seriesAreaStyle, geometryStyle); |
| 129 | + return <Path {...areaProps} key={key} />; |
| 130 | + }; |
| 131 | + private renderAreaLines = ( |
| 132 | + glyph: AreaGeometry, |
| 133 | + areaIndex: number, |
| 134 | + sharedStyle: SharedGeometryStyle, |
| 135 | + highlightedLegendItem: LegendItem | null, |
| 136 | + ): JSX.Element[] => { |
| 137 | + const { lines, color, geometryId, transform, seriesAreaLineStyle } = glyph; |
| 138 | + const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle, seriesAreaLineStyle.opacity); |
131 | 139 |
|
132 | | - const geometryStyle = getGeometryStyle( |
133 | | - geometryId, |
134 | | - this.props.highlightedLegendItem, |
135 | | - sharedStyle, |
136 | | - seriesAreaLineStyle.opacity, |
137 | | - ); |
| 140 | + return lines.map((linePath, lineIndex) => { |
| 141 | + const key = getGeometryIdKey(geometryId, `area-line-${areaIndex}-${lineIndex}`); |
| 142 | + const lineProps = buildLineRenderProps(transform.x, linePath, color, seriesAreaLineStyle, geometryStyle); |
| 143 | + return <Path {...lineProps} key={key} />; |
| 144 | + }); |
| 145 | + }; |
138 | 146 |
|
139 | | - lines.forEach((linePath, lineIndex) => { |
140 | | - const key = `area-${areaIndex}-line-${lineIndex}`; |
141 | | - const lineProps = buildLineRenderProps(transform.x, linePath, color, seriesAreaLineStyle, geometryStyle); |
142 | | - linesToRender.push(<Path {...lineProps} key={key} />); |
143 | | - }); |
| 147 | + private renderPoints = ( |
| 148 | + areaPoints: PointGeometry[], |
| 149 | + areaIndex: number, |
| 150 | + pointStyleProps: PointStyleProps, |
| 151 | + geometryId: GeometryId, |
| 152 | + ): JSX.Element[] => { |
| 153 | + return areaPoints.map((areaPoint, pointIndex) => { |
| 154 | + const { x, y, transform } = areaPoint; |
| 155 | + const key = getGeometryIdKey(geometryId, `area-point-${areaIndex}-${pointIndex}-`); |
| 156 | + const pointProps = buildPointRenderProps(transform.x + x, y, pointStyleProps); |
| 157 | + return <Circle {...pointProps} key={key} />; |
144 | 158 | }); |
145 | | - return linesToRender; |
146 | 159 | }; |
147 | 160 | } |
0 commit comments