Skip to content

Commit

Permalink
feat: add tickLabelRotation and showGridLines features (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmacunningham authored Jan 30, 2019
1 parent 0a314d1 commit 47f118b
Show file tree
Hide file tree
Showing 15 changed files with 603 additions and 167 deletions.
110 changes: 64 additions & 46 deletions src/components/react_canvas/axis.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from 'react';
import { Group, Line, Rect, Text } from 'react-konva';
import { AxisTick, AxisTicksDimensions, isHorizontal, isVertical } from '../../lib/axes/axis_utils';
import {
AxisTick, AxisTicksDimensions, centerRotationOrigin, getHorizontalAxisTickLineProps,
getTickLabelProps, getVerticalAxisTickLineProps, isHorizontal, isVertical,
} from '../../lib/axes/axis_utils';
import { AxisSpec, Position } from '../../lib/series/specs';
import { Theme } from '../../lib/themes/theme';
import { Dimensions } from '../../lib/utils/dimensions';
Expand All @@ -12,6 +15,7 @@ interface AxisProps {
axisPosition: Dimensions;
ticks: AxisTick[];
debug: boolean;
chartDimensions: Dimensions;
}

export class Axis extends React.PureComponent<AxisProps> {
Expand All @@ -23,33 +27,37 @@ export class Axis extends React.PureComponent<AxisProps> {
axes: { tickFontFamily, tickFontSize, tickFontStyle },
} = this.props.chartTheme;
const {
axisSpec: { tickSize, tickPadding, position },
axisTicksDimensions: { maxTickHeight, maxTickWidth },
axisSpec: {
tickSize,
tickPadding,
position,
},
axisTicksDimensions,
debug,
} = this.props;

const tickLabelRotation = this.props.axisSpec.tickLabelRotation || 0;

const tickLabelProps = getTickLabelProps(
tickLabelRotation,
tickSize,
tickPadding,
tick.position,
position,
axisTicksDimensions,
);

const { maxLabelTextWidth, maxLabelTextHeight } = axisTicksDimensions;
const centeredRectProps = centerRotationOrigin(axisTicksDimensions, { x: tickLabelProps.x, y: tickLabelProps.y });

const textProps = {
x: 0,
y: 0,
align: 'center',
width: 0,
height: 0,
verticalAlign: 'middle',
width: maxLabelTextWidth,
height: maxLabelTextHeight,
rotation: tickLabelRotation,
...tickLabelProps,
...centeredRectProps,
};
if (isVertical(position)) {
textProps.y = tick.position - maxTickHeight / 2;
textProps.align = position === Position.Left ? 'right' : 'left';
textProps.x = position === Position.Left ? -maxTickWidth : tickSize + tickPadding;
textProps.height = maxTickHeight;
textProps.width = maxTickWidth;
} else {
textProps.y = position === Position.Top ? 0 : tickSize + tickPadding;
textProps.x = tick.position - maxTickWidth / 2;
textProps.align = 'center';
textProps.height = maxTickHeight;
textProps.width = maxTickWidth;
textProps.verticalAlign = position === Position.Top ? 'bottom' : 'top';
}

return (
<Group key={`tick-${i}`}>
{debug && <Rect {...textProps} stroke="black" strokeWidth={1} fill="violet" />}
Expand All @@ -68,30 +76,40 @@ export class Axis extends React.PureComponent<AxisProps> {
private renderTickLine = (tick: AxisTick, i: number) => {
const {
axisSpec: { tickSize, tickPadding, position },
axisTicksDimensions: { maxTickHeight },
axisTicksDimensions: { maxLabelBboxHeight },
chartDimensions,
chartTheme: { chart: { paddings } },
} = this.props;

const lineProps = [];
const showGridLines = this.props.axisSpec.showGridLines || false;

if (isVertical(position)) {
lineProps[0] = position === Position.Left ? tickPadding : 0;
lineProps[1] = tick.position;
lineProps[2] = position === Position.Left ? tickSize + tickPadding : tickSize;
lineProps[3] = tick.position;
} else {
lineProps[0] = tick.position;
lineProps[1] = position === Position.Top ? maxTickHeight + tickPadding : 0;
lineProps[2] = tick.position;
lineProps[3] = position === Position.Top ? maxTickHeight + tickPadding + tickSize : tickSize;
}
const lineProps = isVertical(position) ?
getVerticalAxisTickLineProps(
showGridLines,
position,
tickPadding,
tickSize,
tick.position,
chartDimensions.width,
paddings,
) : getHorizontalAxisTickLineProps(
showGridLines,
position,
tickPadding,
tickSize,
tick.position,
maxLabelBboxHeight,
chartDimensions.height,
paddings,
);

return <Line key={`tick-${i}`} points={lineProps} stroke={'gray'} strokeWidth={1} />;
}
private renderAxis = () => {
const { ticks, axisPosition } = this.props;
return (
<Group x={axisPosition.left} y={axisPosition.top}>
<Group key="lines">{this.renderLine()}</Group>
<Group key="lines">{this.renderAxisLine()}</Group>
<Group key="tick-lines">{ticks.map(this.renderTickLine)}</Group>
<Group key="ticks">
{ticks.filter((tick) => tick.label !== null).map(this.renderTickLabel)}
Expand All @@ -100,7 +118,7 @@ export class Axis extends React.PureComponent<AxisProps> {
</Group>
);
}
private renderLine = () => {
private renderAxisLine = () => {
const {
axisSpec: { tickSize, tickPadding, position },
axisPosition,
Expand All @@ -116,9 +134,9 @@ export class Axis extends React.PureComponent<AxisProps> {
lineProps[0] = 0;
lineProps[2] = axisPosition.width;
lineProps[1] =
position === Position.Top ? axisTicksDimensions.maxTickHeight + tickSize + tickPadding : 0;
position === Position.Top ? axisTicksDimensions.maxLabelBboxHeight + tickSize + tickPadding : 0;
lineProps[3] =
position === Position.Top ? axisTicksDimensions.maxTickHeight + tickSize + tickPadding : 0;
position === Position.Top ? axisTicksDimensions.maxLabelBboxHeight + tickSize + tickPadding : 0;
}
return <Line points={lineProps} stroke={'gray'} strokeWidth={1} />;
}
Expand All @@ -138,7 +156,7 @@ export class Axis extends React.PureComponent<AxisProps> {
const {
axisPosition: { height },
axisSpec: { title, position, tickSize, tickPadding },
axisTicksDimensions: { maxTickWidth },
axisTicksDimensions: { maxLabelBboxWidth },
chartTheme: {
axes: { titleFontFamily, titleFontSize, titleFontStyle, titlePadding },
},
Expand All @@ -150,8 +168,8 @@ export class Axis extends React.PureComponent<AxisProps> {
const top = height;
const left =
position === Position.Left
? -(maxTickWidth + titleFontSize + titlePadding)
: tickSize + tickPadding + maxTickWidth + titlePadding;
? -(maxLabelBboxWidth + titleFontSize + titlePadding)
: tickSize + tickPadding + maxLabelBboxWidth + titlePadding;

return (
<Group>
Expand Down Expand Up @@ -186,7 +204,7 @@ export class Axis extends React.PureComponent<AxisProps> {
const {
axisPosition: { width, height },
axisSpec: { title, position, tickSize, tickPadding },
axisTicksDimensions: { maxTickHeight },
axisTicksDimensions: { maxLabelBboxHeight },
chartTheme: {
axes: { titleFontSize },
},
Expand All @@ -197,7 +215,7 @@ export class Axis extends React.PureComponent<AxisProps> {
return;
}

const top = position === Position.Top ? -maxTickHeight : maxTickHeight + tickPadding + tickSize;
const top = position === Position.Top ? -maxLabelBboxHeight : maxLabelBboxHeight + tickPadding + tickSize;
const left = 0;
return (
<Group>
Expand All @@ -206,7 +224,7 @@ export class Axis extends React.PureComponent<AxisProps> {
x={left}
y={top}
width={width}
height={maxTickHeight}
height={maxLabelBboxHeight}
stroke="black"
strokeWidth={1}
fill="violet"
Expand Down
21 changes: 12 additions & 9 deletions src/components/react_canvas/reactive_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
axesPositions,
chartTheme,
debug,
chartDimensions,
} = this.props.chartStore!;

const axesComponents: JSX.Element[] = [];
axesVisibleTicks.forEach((axisTicks, axisId) => {
const axisSpec = axesSpecs.get(axisId);
Expand All @@ -153,6 +155,7 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
ticks={ticks}
chartTheme={chartTheme}
debug={debug}
chartDimensions={chartDimensions}
/>,
);
});
Expand Down Expand Up @@ -231,15 +234,15 @@ class Chart extends React.Component<ReactiveChartProps, ReactiveChartState> {
const clippings = debug
? {}
: {
clipX: 0,
clipY: 0,
clipWidth: [90, -90].includes(chartRotation)
? chartDimensions.height
: chartDimensions.width,
clipHeight: [90, -90].includes(chartRotation)
? chartDimensions.width
: chartDimensions.height,
};
clipX: 0,
clipY: 0,
clipWidth: [90, -90].includes(chartRotation)
? chartDimensions.height
: chartDimensions.width,
clipHeight: [90, -90].includes(chartRotation)
? chartDimensions.width
: chartDimensions.height,
};
let brushProps = {};
const isBrushEnabled = this.props.chartStore!.isBrushEnabled();
if (isBrushEnabled) {
Expand Down
26 changes: 13 additions & 13 deletions src/components/svg/axis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ export class Axis extends React.PureComponent<AxisProps> {
className="euiSeriesChartAxis_tickLabel"
key={`tick-${i}`}
{...textProps}
// textAnchor={textProps.textAnchor}
// dominantBaseline={textProps.dominantBaseline}
// transform={transform}
// textAnchor={textProps.textAnchor}
// dominantBaseline={textProps.dominantBaseline}
// transform={transform}
>
{tick.label}
</text>
Expand All @@ -52,7 +52,7 @@ export class Axis extends React.PureComponent<AxisProps> {
private renderTickLine = (tick: AxisTick, i: number) => {
const {
axisSpec: { tickSize, tickPadding, position },
axisTicksDimensions: { maxTickHeight },
axisTicksDimensions: { maxLabelBboxHeight },
} = this.props;

const lineProps: SVGProps<SVGLineElement> = {};
Expand All @@ -65,8 +65,8 @@ export class Axis extends React.PureComponent<AxisProps> {
} else {
lineProps.x1 = tick.position;
lineProps.x2 = tick.position;
lineProps.y1 = position === 'top' ? maxTickHeight + tickPadding : 0;
lineProps.y2 = position === 'top' ? maxTickHeight + tickPadding + tickSize : tickSize;
lineProps.y1 = position === 'top' ? maxLabelBboxHeight + tickPadding : 0;
lineProps.y2 = position === 'top' ? maxLabelBboxHeight + tickPadding + tickSize : tickSize;
}

return <line className="euiSeriesChartAxis_tickLine" key={`tick-${i}`} {...lineProps} />;
Expand Down Expand Up @@ -101,9 +101,9 @@ export class Axis extends React.PureComponent<AxisProps> {
lineProps.x1 = 0;
lineProps.x2 = axisPosition.width;
lineProps.y1 =
position === 'top' ? axisTicksDimensions.maxTickHeight + tickSize + tickPadding : 0;
position === 'top' ? axisTicksDimensions.maxLabelBboxHeight + tickSize + tickPadding : 0;
lineProps.y2 =
position === 'top' ? axisTicksDimensions.maxTickHeight + tickSize + tickPadding : 0;
position === 'top' ? axisTicksDimensions.maxLabelBboxHeight + tickSize + tickPadding : 0;
}
return <line className="euiSeriesChartAxis_line" {...lineProps} />;
}
Expand All @@ -123,7 +123,7 @@ export class Axis extends React.PureComponent<AxisProps> {
const {
axisPosition: { height },
axisSpec: { title, position, tickSize, tickPadding },
axisTicksDimensions: { maxTickWidth },
axisTicksDimensions: { maxLabelBboxWidth },
chartTheme: {
chart: { margins },
},
Expand All @@ -132,8 +132,8 @@ export class Axis extends React.PureComponent<AxisProps> {
const top = height / 2;
const left =
position === Position.Left
? -(maxTickWidth + margins.left / 2)
: tickSize + tickPadding + maxTickWidth + +margins.right / 2;
? -(maxLabelBboxWidth + margins.left / 2)
: tickSize + tickPadding + maxLabelBboxWidth + +margins.right / 2;
const translate = `translate(${left} ${top}) rotate(-90)`;
return (
<g className="euiSeriesChartAxis_axisTitle">
Expand All @@ -147,7 +147,7 @@ export class Axis extends React.PureComponent<AxisProps> {
const {
axisPosition: { width },
axisSpec: { title, position, tickSize, tickPadding },
axisTicksDimensions: { maxTickHeight },
axisTicksDimensions: { maxLabelBboxHeight },
chartTheme: {
chart: { margins },
},
Expand All @@ -156,7 +156,7 @@ export class Axis extends React.PureComponent<AxisProps> {
const top =
position === Position.Top
? -margins.top / 2
: maxTickHeight + tickPadding + tickSize + margins.bottom / 2;
: maxLabelBboxHeight + tickPadding + tickSize + margins.bottom / 2;
const left = width / 2;
const translate = `translate(${left} ${top} )`;
return (
Expand Down
Loading

0 comments on commit 47f118b

Please sign in to comment.