Skip to content

Commit

Permalink
fix: clip overflowing rect/lines/areas (#355)
Browse files Browse the repository at this point in the history
This commit re-apply the clippings for all the geometries but the points to avoid issues with a smaller custom domain than the one computed

fix #354
  • Loading branch information
markov00 authored Aug 27, 2019
1 parent 0f3970c commit 3ff7379
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 48 deletions.
134 changes: 109 additions & 25 deletions .playground/playgroud.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,116 @@
import React from 'react';
import { Axis, Chart, getAxisId, getSpecId, Position, ScaleType, Settings, HistogramBarSeries } from '../src';
import { KIBANA_METRICS } from '../src/utils/data_samples/test_dataset_kibana';
import React, { Fragment } from 'react';
import {
Axis,
Chart,
getAxisId,
getSpecId,
Position,
ScaleType,
Settings,
BarSeries,
LineSeries,
AreaSeries,
} from '../src';

export class Playground extends React.Component {
render() {
return (
<div className="chart">
<Chart>
<Settings
showLegend={true}
xDomain={{
min: KIBANA_METRICS.metrics.kibana_os_load[0].data[0][0] - 10000,
max: KIBANA_METRICS.metrics.kibana_os_load[0].data[18][0] + 10000,
}}
rotation={0}
/>
<Axis id={getAxisId('y')} position={Position.Left} />
<Axis id={getAxisId('x')} position={Position.Bottom} />
<HistogramBarSeries
id={getSpecId('bar')}
yScaleType={ScaleType.Linear}
xScaleType={ScaleType.Time}
xAccessor={0}
yAccessors={[1]}
data={KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 15)}
/>
</Chart>
</div>
<Fragment>
<div className="chart">
<Chart>
<Settings
showLegend={true}
xDomain={{
min: 0.5,
max: 4.5,
}}
/>
<Axis
id={getAxisId('y')}
position={Position.Left}
domain={{
min: 50,
max: 250,
}}
/>
<Axis id={getAxisId('x')} position={Position.Bottom} />
<BarSeries
id={getSpecId('bar')}
yScaleType={ScaleType.Linear}
xScaleType={ScaleType.Linear}
xAccessor={0}
yAccessors={[1]}
data={[[0, 100], [1, 50], [3, 400], [4, 250], [5, 235]]}
/>
</Chart>
</div>
<div className="chart">
<Chart>
<Settings
showLegend={true}
xDomain={{
min: 0.5,
max: 4.5,
}}
/>
<Axis
id={getAxisId('y')}
position={Position.Left}
domain={{
min: 50,
max: 450,
}}
/>
<Axis id={getAxisId('x')} position={Position.Bottom} />
<LineSeries
id={getSpecId('line')}
yScaleType={ScaleType.Linear}
xScaleType={ScaleType.Linear}
xAccessor={0}
yAccessors={[1]}
stackAccessors={[0]}
data={[[0.25, 100], [1, 50], [3, 400], [4, 250], [5, 235]]}
/>
<LineSeries
id={getSpecId('line2')}
yScaleType={ScaleType.Linear}
xScaleType={ScaleType.Linear}
xAccessor={0}
yAccessors={[1]}
stackAccessors={[0]}
data={[[0.25, 100], [0.5, 100], [1, 50], [3, 400], [4, 250], [4.5, 220], [5, 235]]}
/>
</Chart>
</div>
<div className="chart">
<Chart>
<Settings
showLegend={true}
xDomain={{
min: 0.5,
max: 4.5,
}}
/>
<Axis
id={getAxisId('y')}
position={Position.Left}
domain={{
min: 50,
max: 250,
}}
/>
<Axis id={getAxisId('x')} position={Position.Bottom} />
<AreaSeries
id={getSpecId('line')}
yScaleType={ScaleType.Linear}
xScaleType={ScaleType.Linear}
xAccessor={0}
yAccessors={[1]}
data={[[0, 100], [1, 50], [3, 400], [4, 250], [5, 235]]}
/>
</Chart>
</div>
</Fragment>
);
}
}
6 changes: 6 additions & 0 deletions src/chart_types/xy_chart/rendering/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ export function renderPoints(
const pointGeometries = dataset.reduce(
(acc, datum) => {
const x = xScale.scale(datum.x);
if (x < xScale.range[0] || x > xScale.range[1]) {
return acc;
}
const points: PointGeometry[] = [];
const yDatums = [datum.y1];
if (hasY0Accessors) {
Expand All @@ -187,6 +190,9 @@ export function renderPoints(
} else {
y = yScale.scale(yDatum);
}
if (y < yScale.range[1] || y > yScale.range[0]) {
return;
}
const originalY = hasY0Accessors && index === 0 ? datum.initialY0 : datum.initialY1;
const pointGeometry: PointGeometry = {
radius,
Expand Down
8 changes: 4 additions & 4 deletions src/chart_types/xy_chart/store/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,8 @@ describe('Chart State utils', () => {
false,
);
expect(geometries.geometriesCounts.bars).toBe(8);
expect(geometries.geometriesCounts.linePoints).toBe(8);
expect(geometries.geometriesCounts.areasPoints).toBe(8);
expect(geometries.geometriesCounts.linePoints).toBe(6);
expect(geometries.geometriesCounts.areasPoints).toBe(6);
expect(geometries.geometriesCounts.lines).toBe(2);
expect(geometries.geometriesCounts.areas).toBe(2);
});
Expand Down Expand Up @@ -561,8 +561,8 @@ describe('Chart State utils', () => {
false,
);
expect(geometries.geometriesCounts.bars).toBe(8);
expect(geometries.geometriesCounts.linePoints).toBe(8);
expect(geometries.geometriesCounts.areasPoints).toBe(8);
expect(geometries.geometriesCounts.linePoints).toBe(6);
expect(geometries.geometriesCounts.areasPoints).toBe(6);
expect(geometries.geometriesCounts.lines).toBe(2);
expect(geometries.geometriesCounts.areas).toBe(2);
});
Expand Down
28 changes: 20 additions & 8 deletions src/components/react_canvas/area_geometries.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Group as KonvaGroup } from 'konva';
import { Group as KonvaGroup, ContainerConfig } from 'konva';
import React from 'react';
import { Circle, Group, Path } from 'react-konva';
import { LegendItem } from '../../chart_types/xy_chart/legend/legend';
Expand All @@ -23,6 +23,7 @@ interface AreaGeometriesDataProps {
areas: AreaGeometry[];
sharedStyle: SharedGeometryStyle;
highlightedLegendItem: LegendItem | null;
clippings: ContainerConfig;
}
interface AreaGeometriesDataState {
overPoint?: PointGeometry;
Expand All @@ -47,14 +48,14 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps,
);
}
private renderAreaGeoms = (): JSX.Element[] => {
const { sharedStyle, highlightedLegendItem, areas } = this.props;
const { sharedStyle, highlightedLegendItem, areas, clippings } = this.props;
return areas.reduce<JSX.Element[]>((acc, glyph, i) => {
const { seriesAreaLineStyle, seriesAreaStyle, seriesPointStyle, geometryId } = glyph;
if (seriesAreaStyle.visible) {
acc.push(this.renderArea(glyph, sharedStyle, highlightedLegendItem));
acc.push(this.renderArea(glyph, sharedStyle, highlightedLegendItem, clippings));
}
if (seriesAreaLineStyle.visible) {
acc.push(...this.renderAreaLines(glyph, i, sharedStyle, highlightedLegendItem));
acc.push(this.renderAreaLines(glyph, i, sharedStyle, highlightedLegendItem, clippings));
}
if (seriesPointStyle.visible) {
const geometryStyle = getGeometryStyle(geometryId, this.props.highlightedLegendItem, sharedStyle);
Expand All @@ -68,27 +69,38 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps,
glyph: AreaGeometry,
sharedStyle: SharedGeometryStyle,
highlightedLegendItem: LegendItem | null,
clippings: ContainerConfig,
): JSX.Element => {
const { area, color, transform, geometryId, seriesAreaStyle } = glyph;
const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle);
const key = getGeometryIdKey(geometryId, 'area-');
const areaProps = buildAreaRenderProps(transform.x, area, color, seriesAreaStyle, geometryStyle);
return <Path {...areaProps} key={key} />;
return (
<Group {...clippings} key={key}>
<Path {...areaProps} />
</Group>
);
};
private renderAreaLines = (
glyph: AreaGeometry,
areaIndex: number,
sharedStyle: SharedGeometryStyle,
highlightedLegendItem: LegendItem | null,
): JSX.Element[] => {
clippings: ContainerConfig,
): JSX.Element => {
const { lines, color, geometryId, transform, seriesAreaLineStyle } = glyph;
const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle);

return lines.map((linePath, lineIndex) => {
const groupKey = getGeometryIdKey(geometryId, `area-line-${areaIndex}`);
const linesElements = lines.map<JSX.Element>((linePath, lineIndex) => {
const key = getGeometryIdKey(geometryId, `area-line-${areaIndex}-${lineIndex}`);
const lineProps = buildLineRenderProps(transform.x, linePath, color, seriesAreaLineStyle, geometryStyle);
return <Path {...lineProps} key={key} />;
});
return (
<Group {...clippings} key={groupKey}>
{...linesElements}
</Group>
);
};

private renderPoints = (
Expand Down
7 changes: 4 additions & 3 deletions src/components/react_canvas/bar_geometries.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Group as KonvaGroup } from 'konva';
import { Group as KonvaGroup, ContainerConfig } from 'konva';
import React from 'react';
import { Group, Rect } from 'react-konva';
import { animated, Spring } from 'react-spring/renderprops-konva.cjs';
Expand All @@ -12,6 +12,7 @@ interface BarGeometriesDataProps {
bars: BarGeometry[];
sharedStyle: SharedGeometryStyle;
highlightedLegendItem: LegendItem | null;
clippings: ContainerConfig;
}
interface BarGeometriesDataState {
overBar?: BarGeometry;
Expand All @@ -29,9 +30,9 @@ export class BarGeometries extends React.PureComponent<BarGeometriesDataProps, B
};
}
render() {
const { bars } = this.props;
const { bars, clippings } = this.props;
return (
<Group ref={this.barSeriesRef} key={'bar_series'}>
<Group ref={this.barSeriesRef} key={'bar_series'} {...clippings}>
{this.renderBarGeoms(bars)}
</Group>
);
Expand Down
10 changes: 8 additions & 2 deletions src/components/react_canvas/line_geometries.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Group as KonvaGroup } from 'konva';
import { Group as KonvaGroup, ContainerConfig } from 'konva';
import React from 'react';
import { Circle, Group, Path } from 'react-konva';
import { LegendItem } from '../../chart_types/xy_chart/legend/legend';
Expand All @@ -21,6 +21,7 @@ interface LineGeometriesDataProps {
lines: LineGeometry[];
sharedStyle: SharedGeometryStyle;
highlightedLegendItem: LegendItem | null;
clippings: ContainerConfig;
}
interface LineGeometriesDataState {
overPoint?: PointGeometry;
Expand Down Expand Up @@ -79,10 +80,15 @@ export class LineGeometries extends React.PureComponent<LineGeometriesDataProps,
};

getLineToRender(glyph: LineGeometry, sharedStyle: SharedGeometryStyle, key: string) {
const { clippings } = this.props;
const { line, color, transform, geometryId, seriesLineStyle } = glyph;
const geometryStyle = getGeometryStyle(geometryId, this.props.highlightedLegendItem, sharedStyle);
const lineProps = buildLineRenderProps(transform.x, line, color, seriesLineStyle, geometryStyle);
return <Path {...lineProps} key={key} />;
return (
<Group {...clippings} key={key}>
<Path {...lineProps} />
</Group>
);
}

getPointToRender(glyph: LineGeometry, sharedStyle: SharedGeometryStyle, key: string) {
Expand Down
24 changes: 18 additions & 6 deletions src/components/react_canvas/reactive_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Grid } from './grid';
import { LineAnnotation } from './line_annotation';
import { LineGeometries } from './line_geometries';
import { RectAnnotation } from './rect_annotation';
import { ContainerConfig } from 'konva';

interface ReactiveChartProps {
chartStore?: ChartStore; // FIX until we find a better way on ts mobx
Expand Down Expand Up @@ -73,7 +74,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
},
};

renderBarSeries = (): ReactiveChartElementIndex[] => {
renderBarSeries = (clippings: ContainerConfig): ReactiveChartElementIndex[] => {
const { geometries, canDataBeAnimated, chartTheme } = this.props.chartStore!;
if (!geometries) {
return [];
Expand All @@ -87,6 +88,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
bars={geometries.bars}
sharedStyle={chartTheme.sharedStyle}
highlightedLegendItem={highlightedLegendItem}
clippings={clippings}
/>
);

Expand All @@ -97,7 +99,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
},
];
};
renderLineSeries = (): ReactiveChartElementIndex[] => {
renderLineSeries = (clippings: ContainerConfig): ReactiveChartElementIndex[] => {
const { geometries, canDataBeAnimated, chartTheme } = this.props.chartStore!;
if (!geometries) {
return [];
Expand All @@ -112,6 +114,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
lines={geometries.lines}
sharedStyle={chartTheme.sharedStyle}
highlightedLegendItem={highlightedLegendItem}
clippings={clippings}
/>
);

Expand All @@ -122,7 +125,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
},
];
};
renderAreaSeries = (): ReactiveChartElementIndex[] => {
renderAreaSeries = (clippings: ContainerConfig): ReactiveChartElementIndex[] => {
const { geometries, canDataBeAnimated, chartTheme } = this.props.chartStore!;
if (!geometries) {
return [];
Expand All @@ -137,6 +140,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
areas={geometries.areas}
sharedStyle={chartTheme.sharedStyle}
highlightedLegendItem={highlightedLegendItem}
clippings={clippings}
/>
);

Expand Down Expand Up @@ -329,9 +333,17 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
};

sortAndRenderElements() {
const bars = this.renderBarSeries();
const areas = this.renderAreaSeries();
const lines = this.renderLineSeries();
const { chartRotation, chartDimensions } = this.props.chartStore!;
const clippings = {
clipX: 0,
clipY: 0,
clipWidth: [90, -90].includes(chartRotation) ? chartDimensions.height : chartDimensions.width,
clipHeight: [90, -90].includes(chartRotation) ? chartDimensions.width : chartDimensions.height,
};

const bars = this.renderBarSeries(clippings);
const areas = this.renderAreaSeries(clippings);
const lines = this.renderLineSeries(clippings);
const annotations = this.renderAnnotations();

return [...bars, ...areas, ...lines, ...annotations]
Expand Down

0 comments on commit 3ff7379

Please sign in to comment.