Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .storybook/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function loadStories() {
require('../src/stories/interactions.tsx');
require('../src/stories/rotations.tsx');
require('../src/stories/styling.tsx');
require('../src/stories/grid.tsx');
}

configure(loadStories, module);
46 changes: 4 additions & 42 deletions src/components/react_canvas/axis.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react';
import { Group, Line, Rect, Text } from 'react-konva';
import {
AxisTick, AxisTicksDimensions, centerRotationOrigin, getHorizontalAxisGridLineProps,
getHorizontalAxisTickLineProps, getTickLabelProps, getVerticalAxisGridLineProps,
getVerticalAxisTickLineProps, isHorizontal, isVertical, mergeWithDefaultGridLineConfig,
AxisTick, AxisTicksDimensions, centerRotationOrigin,
getHorizontalAxisTickLineProps, getTickLabelProps,
getVerticalAxisTickLineProps, isHorizontal, isVertical,
} from '../../lib/axes/axis_utils';
import { AxisSpec, Position } from '../../lib/series/specs';
import { DEFAULT_GRID_LINE_CONFIG, Theme } from '../../lib/themes/theme';
import { Theme } from '../../lib/themes/theme';
import { Dimensions } from '../../lib/utils/dimensions';

interface AxisProps {
Expand Down Expand Up @@ -74,43 +74,6 @@ export class Axis extends React.PureComponent<AxisProps> {
);
}

private renderGridLine = (tick: AxisTick, i: number) => {
const showGridLines = this.props.axisSpec.showGridLines || false;

if (!showGridLines) {
return null;
}

const {
axisSpec: { tickSize, tickPadding, position, gridLineStyle },
axisTicksDimensions: { maxLabelBboxHeight },
chartDimensions,
chartTheme: { chart: { paddings } },
} = this.props;

const config = gridLineStyle ? mergeWithDefaultGridLineConfig(gridLineStyle) : DEFAULT_GRID_LINE_CONFIG;

const lineProps = isVertical(position) ?
getVerticalAxisGridLineProps(
position,
tickPadding,
tickSize,
tick.position,
chartDimensions.width,
paddings,
) : getHorizontalAxisGridLineProps(
position,
tickPadding,
tickSize,
tick.position,
maxLabelBboxHeight,
chartDimensions.height,
paddings,
);

return <Line key={`tick-${i}`} points={lineProps} {...config} />;
}

private renderTickLine = (tick: AxisTick, i: number) => {
const {
axisSpec: { tickSize, tickPadding, position },
Expand Down Expand Up @@ -139,7 +102,6 @@ export class Axis extends React.PureComponent<AxisProps> {
<Group x={axisPosition.left} y={axisPosition.top}>
<Group key="lines">{this.renderAxisLine()}</Group>
<Group key="tick-lines">{ticks.map(this.renderTickLine)}</Group>
<Group key="grid-lines">{ticks.map(this.renderGridLine)}</Group>
<Group key="ticks">
{ticks.filter((tick) => tick.label !== null).map(this.renderTickLabel)}
</Group>
Expand Down
39 changes: 39 additions & 0 deletions src/components/react_canvas/grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { Group, Line } from 'react-konva';
import {
AxisLinePosition, mergeWithDefaultGridLineConfig,
} from '../../lib/axes/axis_utils';
import { DEFAULT_GRID_LINE_CONFIG, GridLineConfig } from '../../lib/themes/theme';
import { Dimensions } from '../../lib/utils/dimensions';

interface GridProps {
chartDimensions: Dimensions;
debug: boolean;
gridLineStyle: GridLineConfig | undefined;
linesPositions: AxisLinePosition[];
}

export class Grid extends React.PureComponent<GridProps> {
render() {
return this.renderGrid();
}
private renderGridLine = (linePosition: AxisLinePosition, i: number) => {
const {
gridLineStyle,
} = this.props;

const config = gridLineStyle ? mergeWithDefaultGridLineConfig(gridLineStyle) : DEFAULT_GRID_LINE_CONFIG;

return <Line key={`tick-${i}`} points={linePosition} {...config} />;
}

private renderGrid = () => {
const { chartDimensions, linesPositions } = this.props;

return (
<Group x={chartDimensions.left} y={chartDimensions.top}>
<Group key="grid-lines">{linesPositions.map(this.renderGridLine)}</Group>
</Group>
);
}
}
38 changes: 38 additions & 0 deletions src/components/react_canvas/reactive_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BrushExtent } from '../../state/utils';
import { AreaGeometries } from './area_geometries';
import { Axis } from './axis';
import { BarGeometries } from './bar_geometries';
import { Grid } from './grid';
import { LineGeometries } from './line_geometries';

interface ReactiveChartProps {
Expand Down Expand Up @@ -161,6 +162,33 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
});
return axesComponents;
}

renderGrids = () => {
const {
axesGridLinesPositions,
axesSpecs,
chartDimensions,
debug,
} = this.props.chartStore!;

const gridComponents: JSX.Element[] = [];
axesGridLinesPositions.forEach((axisGridLinesPositions, axisId) => {
const axisSpec = axesSpecs.get(axisId);
if (axisSpec && axisGridLinesPositions.length > 0) {
gridComponents.push(
<Grid
key={`axis-grid-${axisId}`}
chartDimensions={chartDimensions}
debug={debug}
gridLineStyle={axisSpec.gridLineStyle}
linesPositions={axisGridLinesPositions}
/>,
);
}
});
return gridComponents;
}

renderBrushTool = () => {
const { brushing, brushStart, brushEnd } = this.state;
const { chartDimensions, chartRotation, chartTransform } = this.props.chartStore!;
Expand Down Expand Up @@ -243,6 +271,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
? chartDimensions.width
: chartDimensions.height,
};

let brushProps = {};
const isBrushEnabled = this.props.chartStore!.isBrushEnabled();
if (isBrushEnabled) {
Expand All @@ -253,6 +282,13 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
};
}

const gridClippings = {
clipX: chartDimensions.left,
clipY: chartDimensions.top,
clipWidth: chartDimensions.width,
clipHeight: chartDimensions.height,
};

return (
<div
style={{
Expand All @@ -273,6 +309,8 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
}}
{...brushProps}
>
<Layer hitGraphEnabled={false} {...gridClippings}>{this.renderGrids()}</Layer>

<Layer
ref={this.renderingLayerRef}
x={chartDimensions.left + chartTransform.x}
Expand Down
50 changes: 4 additions & 46 deletions src/lib/axes/axis_utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { XDomain } from '../series/domains/x_domain';
import { YDomain } from '../series/domains/y_domain';
import { Position } from '../series/specs';
import { DEFAULT_THEME } from '../themes/theme';
import { Margins } from '../utils/dimensions';
import { getAxisId, getGroupId } from '../utils/ids';
import { ScaleType } from '../utils/scales/scales';
import {
Expand Down Expand Up @@ -454,63 +453,22 @@ describe('Axis computational utils', () => {
});

test('should compute axis grid line positions', () => {
const tickPadding = 5;
const tickSize = 10;
const tickPosition = 10;
const maxLabelBboxHeight = 20;
const chartWidth = 100;
const chartHeight = 200;
const paddings: Margins = {
top: 3,
left: 6,
bottom: 9,
right: 12,
};

const leftAxisGridLinePositions = getVerticalAxisGridLineProps(
Position.Left,
tickPadding,
tickSize,
tickPosition,
chartWidth,
paddings,
);

expect(leftAxisGridLinePositions).toEqual([21, 10, 121, 10]);

const rightAxisGridLinePositions = getVerticalAxisGridLineProps(
Position.Right,
tickPadding,
tickSize,
const verticalAxisGridLinePositions = getVerticalAxisGridLineProps(
tickPosition,
chartWidth,
paddings,
);

expect(rightAxisGridLinePositions).toEqual([-112, 10, -12, 10]);

const topAxisGridLinePositions = getHorizontalAxisGridLineProps(
Position.Top,
tickPadding,
tickSize,
tickPosition,
maxLabelBboxHeight,
chartHeight,
paddings,
);

expect(topAxisGridLinePositions).toEqual([10, 38, 10, 238]);
expect(verticalAxisGridLinePositions).toEqual([0, 10, 100, 10]);

const bottomAxisGridLinePositions = getHorizontalAxisGridLineProps(
Position.Bottom,
tickPadding,
tickSize,
const horizontalAxisGridLinePositions = getHorizontalAxisGridLineProps(
tickPosition,
maxLabelBboxHeight,
chartHeight,
paddings,
);

expect(bottomAxisGridLinePositions).toEqual([10, -209, 10, -9]);
expect(horizontalAxisGridLinePositions).toEqual([10, 0, 10, 200]);
});
});
66 changes: 35 additions & 31 deletions src/lib/axes/axis_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { AxisId } from '../utils/ids';
import { Scale, ScaleType } from '../utils/scales/scales';
import { BBox, BBoxCalculator } from './bbox_calculator';

export type AxisLinePosition = [number, number, number, number];

export interface AxisTick {
value: number | string;
label: string;
Expand Down Expand Up @@ -246,7 +248,7 @@ export function getVerticalAxisTickLineProps(
tickPadding: number,
tickSize: number,
tickPosition: number,
): number[] {
): AxisLinePosition {
const isLeftAxis = position === Position.Left;
const y = tickPosition;
const x1 = isLeftAxis ? tickPadding : 0;
Expand All @@ -261,7 +263,7 @@ export function getHorizontalAxisTickLineProps(
tickSize: number,
tickPosition: number,
labelHeight: number,
): number[] {
): AxisLinePosition {
const isTopAxis = position === Position.Top;
const x = tickPosition;
const y1 = isTopAxis ? labelHeight + tickPadding : 0;
Expand All @@ -271,42 +273,17 @@ export function getHorizontalAxisTickLineProps(
}

export function getVerticalAxisGridLineProps(
position: Position,
tickPadding: number,
tickSize: number,
tickPosition: number,
chartWidth: number,
paddings: Margins,
): number[] {
const isLeftAxis = position === Position.Left;
const y = tickPosition;

const leftX1 = tickSize + tickPadding + paddings.left;
const rightX1 = - chartWidth - paddings.right;

const x1 = isLeftAxis ? leftX1 : rightX1;

return [x1, y, x1 + chartWidth, y];
): AxisLinePosition {
return [0, tickPosition, chartWidth, tickPosition];
}

export function getHorizontalAxisGridLineProps(
position: Position,
tickPadding: number,
tickSize: number,
tickPosition: number,
labelHeight: number,
chartHeight: number,
paddings: Margins,
): number[] {
const isTopAxis = position === Position.Top;
const x = tickPosition;

const topY1 = labelHeight + tickPadding + tickSize + paddings.top;
const bottomY1 = - chartHeight - paddings.bottom;

const y1 = isTopAxis ? topY1 : bottomY1;

return [x, y1, x, y1 + chartHeight];
): AxisLinePosition {
return [tickPosition, 0, tickPosition, chartHeight];
}

export function mergeWithDefaultGridLineConfig(config: GridLineConfig): GridLineConfig {
Expand Down Expand Up @@ -501,6 +478,7 @@ export function getAxisTicksPositions(
const axisPositions: Map<AxisId, Dimensions> = new Map();
const axisVisibleTicks: Map<AxisId, AxisTick[]> = new Map();
const axisTicks: Map<AxisId, AxisTick[]> = new Map();
const axisGridLinesPositions: Map<AxisId, AxisLinePosition[]> = new Map();

let cumTopSum = 0;
let cumBottomSum = chartConfig.paddings.bottom;
Expand Down Expand Up @@ -560,6 +538,14 @@ export function getAxisTicksPositions(
chartRotation,
);

if (axisSpec.showGridLines) {
const isVerticalAxis = isVertical(axisSpec.position);
const gridLines = visibleTicks.map((tick: AxisTick): AxisLinePosition => {
return computeAxisGridLinePositions(isVerticalAxis, tick.position, chartDimensions);
});
axisGridLinesPositions.set(id, gridLines);
}

const { titleFontSize, titlePadding } = chartTheme.axes;
const axisTitleHeight = titleFontSize + titlePadding;

Expand Down Expand Up @@ -587,9 +573,27 @@ export function getAxisTicksPositions(
axisPositions,
axisTicks,
axisVisibleTicks,
axisGridLinesPositions,
};
}

function computeAxisGridLinePositions(
isVerticalAxis: boolean,
tickPosition: number,
chartDimensions: Dimensions,
): AxisLinePosition {
const positions = isVerticalAxis ?
getVerticalAxisGridLineProps(
tickPosition,
chartDimensions.width,
) : getHorizontalAxisGridLineProps(
tickPosition,
chartDimensions.height,
);

return positions;
}

function getVerticalDomain(
xDomain: XDomain,
yDomain: YDomain[],
Expand Down
Loading