Skip to content

Commit a9307ef

Browse files
authored
feat: add band area chart (#157)
This PR adds a `y0Accessors` prop for each `SeriesSpec`: this property can be used to describe a dataset with bands ( with a min and max value for each data point). It's mainly used for with `AreaSeries` to describe a bounded area chart, bounded on the y axis. The `y0` value, is usually a lower value than the `y1`, it will be rendered perpendicularly to the `y1` point. On a standard area chart, the `y0` value usually correspond to `0` or to the previous value in the stack. In a band-area chart, the `y0` can be any value below the `y1` value. It can also be applied to bar charts, with some limitations as described below. On a barchart, the `y0` value is the bottom edge of the bar. On a stacked bar/area chart a series with a `y0Accessor` will be stacked on top of the below series stacking the below series `y1` value with the band series `y0` value. This means that if the below series at a point X has an height of `10`, and the bound series has the following values: `y0: 2, y1: 5` the resulting chart will push the bound series to the top starting using the following values: `y0:12, y1: 15`. The `IndexedGeometry` object is also refactored. To limit amount of redundant code/memory object we used the same `Geometry` elements used on the highlight/hover process. The structure of `IndexedGeometry` is slightly changed, to avoid duplicate values and to simplify tooltip formatting when rendering either y1 and y0 values. I've currently removed from the `indexedGeometries` map all geometry with `null` values on `y1`. This leads to a minor problem: we are not showing any tooltip on that interval, the tooltip of the crosshair is never shown. close #144
1 parent 21316d1 commit a9307ef

35 files changed

+7493
-850
lines changed

src/components/highlighter.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { inject, observer } from 'mobx-react';
22
import React from 'react';
3+
import { isPointGeometry } from '../lib/series/rendering';
34
import { ChartStore } from '../state/chart_state';
45

56
interface HighlighterProps {
@@ -21,26 +22,31 @@ class HighlighterComponent extends React.Component<HighlighterProps> {
2122
return (
2223
<svg className="elasticChartsHighlighter">
2324
<g transform={`translate(${left}, ${top}) rotate(${chartRotation})`}>
24-
{highlightedGeometries.map((highlightedGeometry, i) => {
25-
const {
26-
color,
27-
geom: { x, y, width, height, isPoint },
28-
} = highlightedGeometry;
29-
if (isPoint) {
25+
{highlightedGeometries.map((geom, i) => {
26+
const { color, x, y } = geom;
27+
if (isPointGeometry(geom)) {
3028
return (
3129
<circle
3230
key={i}
33-
cx={x}
31+
cx={x + geom.transform.x}
3432
cy={y}
35-
r={width}
33+
r={geom.radius}
3634
stroke={color}
3735
strokeWidth={4}
3836
fill="transparent"
3937
/>
4038
);
4139
}
4240
return (
43-
<rect key={i} x={x} y={y} width={width} height={height} fill="white" opacity={0.4} />
41+
<rect
42+
key={i}
43+
x={x}
44+
y={y}
45+
width={geom.width}
46+
height={geom.height}
47+
fill="white"
48+
opacity={0.4}
49+
/>
4450
);
4551
})}
4652
</g>

src/components/react_canvas/area_geometries.tsx

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class AreaGeometries extends React.PureComponent<
4242
return (
4343
<Group ref={this.barSeriesRef} key={'bar_series'}>
4444
{area.visible && this.renderAreaGeoms()}
45-
{line.visible && this.renderAreaLine()}
45+
{line.visible && this.renderAreaLines()}
4646
{point.visible && this.renderAreaPoints()}
4747
</Group>
4848
);
@@ -132,46 +132,51 @@ export class AreaGeometries extends React.PureComponent<
132132
}
133133
});
134134
}
135-
private renderAreaLine = (): JSX.Element[] => {
135+
private renderAreaLines = (): JSX.Element[] => {
136136
const { areas, sharedStyle } = this.props;
137137
const { strokeWidth } = this.props.style.line;
138-
139-
return areas.map((glyph, i) => {
140-
const { line, color, transform, geometryId } = glyph;
138+
const linesToRender: JSX.Element[] = [];
139+
areas.forEach((glyph, areaIndex) => {
140+
const { lines, color, geometryId } = glyph;
141141

142142
const geometryStyle = getGeometryStyle(
143143
geometryId,
144144
this.props.highlightedLegendItem,
145145
sharedStyle,
146146
);
147147

148-
if (this.props.animated) {
149-
return (
150-
<Group key={`area-line-group-${i}`} x={transform.x}>
151-
<Spring native from={{ line }} to={{ line }}>
152-
{(props: { line: string }) => {
153-
const lineProps = buildAreaLineProps({
154-
index: i,
155-
linePath: props.line,
156-
color,
157-
strokeWidth,
158-
geometryStyle,
159-
});
160-
return <animated.Path {...lineProps} />;
161-
}}
162-
</Spring>
163-
</Group>
164-
);
165-
} else {
148+
lines.forEach((linePath, lineIndex) => {
166149
const lineProps = buildAreaLineProps({
167-
index: i,
168-
linePath: line,
150+
areaIndex,
151+
lineIndex,
152+
linePath,
169153
color,
170154
strokeWidth,
171155
geometryStyle,
172156
});
173-
return <Path {...lineProps} />;
174-
}
157+
linesToRender.push(<Path {...lineProps} />);
158+
});
175159
});
160+
return linesToRender;
161+
// if (this.props.animated) {
162+
// return (
163+
// <Group key={`area-line-group-${i}`} x={transform.x}>
164+
// <Spring native from={{ line }} to={{ line }}>
165+
// {(props: { line: string }) => {
166+
// const lineProps = buildAreaLineProps({
167+
// index: i,
168+
// linePath: props.line,
169+
// color,
170+
// strokeWidth,
171+
// geometryStyle,
172+
// });
173+
// return <animated.Path {...lineProps} />;
174+
// }}
175+
// </Spring>
176+
// </Group>
177+
// );
178+
// } else {
179+
180+
// }
176181
}
177182
}

src/components/react_canvas/utils/rendering_props_utils.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ describe('[canvas] Area Geometries props', () => {
8080
});
8181
test('can build area line path props', () => {
8282
const props = buildAreaLineProps({
83-
index: 1,
83+
areaIndex: 1,
84+
lineIndex: 2,
8485
linePath: 'M0,0L10,10Z',
8586
color: 'red',
8687
strokeWidth: 1,
@@ -89,7 +90,7 @@ describe('[canvas] Area Geometries props', () => {
8990
},
9091
});
9192
expect(props).toEqual({
92-
key: `area-line-1`,
93+
key: `area-1-line-2`,
9394
data: 'M0,0L10,10Z',
9495
stroke: 'red',
9596
strokeWidth: 1,

src/components/react_canvas/utils/rendering_props_utils.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,22 @@ export function buildAreaProps({
5757
}
5858

5959
export function buildAreaLineProps({
60-
index,
60+
areaIndex,
61+
lineIndex,
6162
linePath,
6263
color,
6364
strokeWidth,
6465
geometryStyle,
6566
}: {
66-
index: number;
67+
areaIndex: number;
68+
lineIndex: number;
6769
linePath: string;
6870
color: string;
6971
strokeWidth: number;
7072
geometryStyle: GeometryStyle;
7173
}) {
7274
return {
73-
key: `area-line-${index}`,
75+
key: `area-${areaIndex}-line-${lineIndex}`,
7476
data: linePath,
7577
stroke: color,
7678
strokeWidth,

0 commit comments

Comments
 (0)