Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(series): markSizeAccessor and BubbleSeries (alpha) #559

Merged
merged 60 commits into from
Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
1d937ce
feat(series): dot accessor
nickofthyme Mar 31, 2020
aa434d4
refactor: tweak radius calculation
nickofthyme Mar 31, 2020
627fe6e
chore: add dot value to tooltip
nickofthyme Apr 1, 2020
39f1066
refactor: cleanup
nickofthyme Apr 1, 2020
aca819a
fix: dot labeling when value is null
nickofthyme Apr 1, 2020
46d8f17
fix: remove unnecessary errors
nickofthyme Apr 1, 2020
7bbeba8
refactor: rename dot to mark throughout
nickofthyme Apr 1, 2020
cd88f07
fix: move delauney types to dev deps
nickofthyme Apr 1, 2020
d3f1e2b
refactor: check for markSizeAccessor before creating radius fn
nickofthyme Apr 1, 2020
b1d48ff
fix: remove pow shorthand
nickofthyme Apr 1, 2020
7fc9950
fix: linear map set method logic
nickofthyme Apr 1, 2020
b32a7e6
refactor: change voronoi naming
nickofthyme Apr 2, 2020
8ff0c27
refactor: point geo check before spatial uppsert
nickofthyme Apr 2, 2020
c2311a9
fix: various errors found in VRT
nickofthyme Apr 3, 2020
fab6300
Merge branch 'master' into feat/dot-accessor
nickofthyme Apr 3, 2020
28ec199
fix: update snapshots with VRT changes
nickofthyme Apr 6, 2020
9063b3e
fix: ts type errors and improve scale types
nickofthyme Apr 7, 2020
9f0b7ab
fix: update scale error handling
nickofthyme Apr 7, 2020
108d6a5
fix: type errors in unit tests
nickofthyme Apr 7, 2020
c638e14
fix: update jest test snapshots
nickofthyme Apr 7, 2020
a0f237a
fix: fix failed jest tests from mark changes
nickofthyme Apr 7, 2020
370d9fa
fix: scaleOrThrow offset
nickofthyme Apr 8, 2020
f6a3b9f
fix: function return type
nickofthyme Apr 8, 2020
dd6e157
fix: function return type error
nickofthyme Apr 8, 2020
efbb203
cleanup: random number generator code
nickofthyme Apr 8, 2020
b14d7e4
fix: ie11 issue, add delaunay file locally
nickofthyme Apr 8, 2020
e487540
Merge branch 'master' into feat/dot-accessor
nickofthyme Apr 8, 2020
af41659
fix: transpile error in ie11, verify bubble chart in ie 11
nickofthyme Apr 9, 2020
3de4a69
refactor: add BubbleSeries type, upadated to use spatial index
nickofthyme Apr 9, 2020
3a00802
fix: coincident point issue, temporary fix
nickofthyme Apr 9, 2020
28d2643
cleanup: random value logic and bubble examples
nickofthyme Apr 9, 2020
46cc771
Merge branch 'master' into feat/dot-accessor
nickofthyme Apr 9, 2020
6f8a426
chore: add delaunay to prettier ignore
nickofthyme Apr 9, 2020
24824da
fix: wrangle delaunay types in once and forall
nickofthyme Apr 9, 2020
a85993c
docs: fix license headers and NOTICE file
markov00 Apr 10, 2020
5c45f80
cleanup: variable naming
nickofthyme Apr 13, 2020
70772d1
fix: issue related to buffer and mixed charts
nickofthyme Apr 13, 2020
9228104
feat: allow rednering of grouped point sets on single layer
nickofthyme Apr 13, 2020
f92e8df
docs: update bubble section with alpha
nickofthyme Apr 14, 2020
56649d0
test: fix broken tests for isPointOnGeometry
nickofthyme Apr 14, 2020
7fad07c
test: mocks cleanup, clean fix ydomain tests
nickofthyme Apr 14, 2020
c01ff6e
feat: mergePartial to allow Maps and Sets
nickofthyme Apr 15, 2020
bce7d9f
test: Rendering bands and geometry mocks
nickofthyme Apr 15, 2020
e5d8a2c
feat: add option to mergePartial and fix type
nickofthyme Apr 15, 2020
dc5ba80
test: refactor rendering bars tests to use mocks
nickofthyme Apr 15, 2020
7c2b6eb
fix: duplicate values in tooltip
nickofthyme Apr 15, 2020
460ea2e
fix: tooltip header visibility condition
nickofthyme Apr 15, 2020
824bd09
fix: jest-extended matchers setup
nickofthyme Apr 15, 2020
5ee40ae
fix: ordinal values with BubbleSeries
nickofthyme Apr 15, 2020
804e023
refactor: remove flatMap usage, fails in jest env
nickofthyme Apr 15, 2020
dfa7cc1
fix: prevent spatial index from returning values when point is out of…
nickofthyme Apr 15, 2020
bf94125
test: add test coverage for changes
nickofthyme Apr 15, 2020
529d7e0
Merge branch 'master' into feat/dot-accessor
nickofthyme Apr 15, 2020
53ae456
fix: tooltip header for bars, update screenshots
nickofthyme Apr 16, 2020
0b9d3ca
fix: ordinal spatial selection
nickofthyme Apr 16, 2020
8d54786
fix: internal type error
nickofthyme Apr 17, 2020
c46965b
test: fix test to match new indexing logic
nickofthyme Apr 17, 2020
ddcb014
chore: cleanup internal types and comments
nickofthyme Apr 17, 2020
6706665
Merge branch 'master' into feat/dot-accessor
nickofthyme Apr 17, 2020
d3bdb4f
Merge branch 'master' into feat/dot-accessor
nickofthyme Apr 21, 2020
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
109 changes: 63 additions & 46 deletions .playground/playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,74 @@
* under the License. */

import React from 'react';
import {
Chart,
ScaleType,
Position,
Axis,
LineSeries,
LineAnnotation,
RectAnnotation,
AnnotationDomainTypes,
LineAnnotationDatum,
RectAnnotationDatum,
} from '../src';
import { SeededDataGenerator } from '../src/mocks/utils';

export class Playground extends React.Component<{}, { isSunburstShown: boolean }> {
render() {
const dg = new SeededDataGenerator();
const data = dg.generateGroupedSeries(10, 2).map((item) => ({
...item,
y1: item.y + 100,
}));
const lineDatum: LineAnnotationDatum[] = [{ dataValue: 321321 }];
const rectDatum: RectAnnotationDatum[] = [{ coordinates: { x1: 100 } }];
import { Delaunay } from 'd3-delaunay';
import { getRandomNumberGenerator } from '../src/mocks/utils';

export class Playground extends React.Component<{}, { ready: boolean }> {
private readonly canvasRef: React.RefObject<HTMLCanvasElement>;
private ctx: CanvasRenderingContext2D | null;
private delaunay: Delaunay<any> | null;
private points: number[][] = [];

constructor(props: any) {
super(props);
this.canvasRef = React.createRef();
this.ctx = null;
this.delaunay = null;

this.state = { ready: false };
}

componentDidMount() {
if (!this.ctx) {
this.tryCanvasContext();
this.setState({ ready: true });
}
}

tryCanvasContext() {
const canvas = this.canvasRef.current;
const ctx = canvas && canvas.getContext('2d');

if (ctx) {
const rng = getRandomNumberGenerator();
this.ctx = ctx;

this.points = new Array(10).fill(1).map(() => [rng(0, 100), rng(0, 100)]);
console.table(this.points);

this.delaunay = Delaunay.from(this.points);
const voronoi = this.delaunay.voronoi();

this.ctx.beginPath();
voronoi.render(this.ctx);
this.ctx.lineWidth = 2;
this.ctx.strokeStyle = 'blue';
this.ctx.stroke();
}
}

handleHover = (event: React.MouseEvent) => {
if (this.delaunay) {
const index = this.delaunay.find(event.nativeEvent.offsetX, event.nativeEvent.offsetY);

console.log(this.points[index]);
}
};

render() {
return (
<>
<div className="chart">
<Chart>
<Axis id="y1" position={Position.Left} title="y1" />
<Axis id="y2" domain={{ fit: true }} groupId="g2" position={Position.Right} title="y2" />
<Axis id="x" position={Position.Bottom} title="x" />
<LineSeries
id="line1"
xScaleType={ScaleType.Linear}
xAccessor="x"
yAccessors={['y']}
splitSeriesAccessors={['g']}
data={data}
/>
<LineSeries
id="line2"
groupId="g2"
xScaleType={ScaleType.Linear}
xAccessor="x"
yAccessors={['y1']}
splitSeriesAccessors={['g']}
data={data}
/>
<LineAnnotation id="sss" dataValues={lineDatum} domainType={AnnotationDomainTypes.XDomain} />
<RectAnnotation id="111" dataValues={rectDatum} />
</Chart>
<canvas
onMouseMove={this.handleHover}
style={{
height: '100%',
width: '100%',
}}
ref={this.canvasRef}
></canvas>
</div>
</>
);
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,13 @@
"webpack-dev-server": "^3.3.1"
},
"dependencies": {
"@types/d3-delaunay": "^4.1.0",
markov00 marked this conversation as resolved.
Show resolved Hide resolved
"@types/d3-shape": "^1.3.1",
"classnames": "^2.2.6",
"d3-array": "^1.2.4",
"d3-collection": "^1.0.7",
"d3-color": "^1.4.0",
"d3-delaunay": "^5.2.1",
"d3-scale": "^1.0.7",
"d3-shape": "^1.3.4",
"eslint-plugin-unicorn": "^16.1.1",
Expand Down
22 changes: 15 additions & 7 deletions src/chart_types/xy_chart/renderer/canvas/areas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ interface AreaGeometriesProps {
export function renderAreas(ctx: CanvasRenderingContext2D, props: AreaGeometriesProps) {
withContext(ctx, (ctx) => {
const { sharedStyle, highlightedLegendItem, areas, clippings } = props;

withClip(ctx, clippings, (ctx: CanvasRenderingContext2D) => {
ctx.save();

Expand All @@ -58,16 +59,22 @@ export function renderAreas(ctx: CanvasRenderingContext2D, props: AreaGeometries
ctx.clip();
ctx.restore();
});
for (let i = 0; i < areas.length; i++) {
const glyph = areas[i];
const { seriesPointStyle, seriesIdentifier } = glyph;

areas.forEach((area) => {
const { seriesPointStyle, seriesIdentifier } = area;
if (seriesPointStyle.visible) {
const geometryStateStyle = getGeometryStateStyle(seriesIdentifier, highlightedLegendItem, sharedStyle);
withContext(ctx, () => {
renderPoints(ctx, glyph.points, seriesPointStyle, geometryStateStyle);
});
withClip(
ctx,
clippings,
(ctx) => {
renderPoints(ctx, area.points, seriesPointStyle, geometryStateStyle);
},
// TODO: add padding over clipping
area.points[0]?.value.dot !== null,
);
}
}
});
});
}

Expand All @@ -83,6 +90,7 @@ function renderArea(
const fill = buildAreaStyles(color, seriesAreaStyle, geometryStateStyle);
renderAreaPath(ctx, transform.x, area, fill, clippedRanges, clippings);
}

function renderAreaLines(
ctx: CanvasRenderingContext2D,
glyph: AreaGeometry,
Expand Down
16 changes: 11 additions & 5 deletions src/chart_types/xy_chart/renderer/canvas/lines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { getGeometryStateStyle } from '../../rendering/rendering';
import { LineGeometry } from '../../../../utils/geometry';
import { SharedGeometryStateStyle } from '../../../../utils/themes/theme';
import { LegendItem } from '../../legend/legend';
import { withContext } from '../../../../renderers/canvas';
import { withContext, withClip } from '../../../../renderers/canvas';
import { renderPoints } from './points';
import { renderLinePaths } from './primitives/path';
import { Rect } from '../../../../geoms/types';
Expand All @@ -47,10 +47,16 @@ export function renderLines(ctx: CanvasRenderingContext2D, props: LineGeometries
}

if (seriesPointStyle.visible) {
withContext(ctx, (ctx) => {
const geometryStyle = getGeometryStateStyle(line.seriesIdentifier, highlightedLegendItem, sharedStyle);
renderPoints(ctx, line.points, line.seriesPointStyle, geometryStyle);
});
withClip(
ctx,
clippings,
(ctx) => {
const geometryStyle = getGeometryStateStyle(line.seriesIdentifier, highlightedLegendItem, sharedStyle);
renderPoints(ctx, line.points, line.seriesPointStyle, geometryStyle);
},
// TODO: add padding over clipping
line.points[0]?.value.dot !== null,
);
}
});
});
Expand Down
30 changes: 19 additions & 11 deletions src/chart_types/xy_chart/renderer/canvas/points.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import { PointGeometry } from '../../../../utils/geometry';
import { PointStyle, GeometryStateStyle } from '../../../../utils/themes/theme';
import { renderCircle } from './primitives/arc';
import { Circle } from '../../../../geoms/types';
import { Circle, Stroke, Fill } from '../../../../geoms/types';
import { buildPointStyles } from './styles/point';

export function renderPoints(
Expand All @@ -28,16 +28,24 @@ export function renderPoints(
themeStyle: PointStyle,
geometryStateStyle: GeometryStateStyle,
) {
return points.map((point) => {
const { x, y, color, transform, styleOverrides } = point;
const { fill, stroke, radius } = buildPointStyles(color, themeStyle, geometryStateStyle, styleOverrides);
points
.map<[Circle, Fill, Stroke]>((point) => {
const { x, y, color, radius, transform, styleOverrides } = point;
const { fill, stroke, radius: radiusOverride } = buildPointStyles(
color,
themeStyle,
geometryStateStyle,
styleOverrides,
);

const circle: Circle = {
x: x + transform.x,
y,
radius,
};
const circle: Circle = {
x: x + transform.x,
y,
radius: radius || radiusOverride,
};

renderCircle(ctx, circle, fill, stroke);
});
return [circle, fill, stroke];
})
.sort(([{ radius: a }], [{ radius: b }]) => b - a)
.forEach((args) => renderCircle(ctx, ...args));
}
24 changes: 20 additions & 4 deletions src/chart_types/xy_chart/renderer/canvas/renderers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export function renderXYChartCanvas2d(
chartTransform,
chartRotation,
geometries,
geometriesIndex,
theme,
highlightedLegendItem,
annotationDimensions,
Expand Down Expand Up @@ -160,18 +161,21 @@ export function renderXYChartCanvas2d(
);
});
},
// rendering debugger
(ctx: CanvasRenderingContext2D) => {
if (!debug) {
return;
}
withContext(ctx, (ctx) => {
const { left, top, width, height } = chartDimensions;

renderDebugRect(
ctx,
{
x: chartDimensions.left,
y: chartDimensions.top,
width: chartDimensions.width,
height: chartDimensions.height,
x: left,
y: top,
width,
height,
},
{
color: stringToRGB('transparent'),
Expand All @@ -182,6 +186,18 @@ export function renderXYChartCanvas2d(
dash: [4, 4],
},
);

const voronoi = geometriesIndex.voronoi([0, 0, width, height]);

if (voronoi) {
ctx.beginPath();
ctx.translate(left, top);
ctx.setLineDash([5, 5]);
voronoi.render(ctx);
ctx.lineWidth = 1;
ctx.strokeStyle = 'blue';
ctx.stroke();
}
});
},
]);
Expand Down
4 changes: 4 additions & 0 deletions src/chart_types/xy_chart/renderer/canvas/xy_chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ import { renderXYChartCanvas2d } from './renderers';
import { isChartEmptySelector } from '../../state/selectors/is_chart_empty';
import { deepEqual } from '../../../../utils/fast_deep_equal';
import { Rotation } from '../../../../utils/commons';
import { IndexedGeometryMap } from '../../utils/indexed_geometry_map';

export interface ReactiveChartStateProps {
initialized: boolean;
debug: boolean;
isChartEmpty: boolean;
geometries: Geometries;
geometriesIndex: IndexedGeometryMap;
theme: Theme;
chartContainerDimensions: Dimensions;
chartRotation: Rotation;
Expand Down Expand Up @@ -180,6 +182,7 @@ const DEFAULT_PROPS: ReactiveChartStateProps = {
lines: [],
points: [],
},
geometriesIndex: new IndexedGeometryMap(),
theme: LIGHT_THEME,
chartContainerDimensions: {
width: 0,
Expand Down Expand Up @@ -222,6 +225,7 @@ const mapStateToProps = (state: GlobalChartState): ReactiveChartStateProps => {
isChartEmpty: isChartEmptySelector(state),
debug: getSettingsSpecSelector(state).debug,
geometries: computeSeriesGeometriesSelector(state).geometries,
geometriesIndex: computeSeriesGeometriesSelector(state).geometriesIndex,
markov00 marked this conversation as resolved.
Show resolved Hide resolved
theme: getChartThemeSelector(state),
chartContainerDimensions: getChartContainerDimensionsSelector(state),
highlightedLegendItem: getHighlightedSeriesSelector(state),
Expand Down
4 changes: 3 additions & 1 deletion src/chart_types/xy_chart/renderer/dom/highlighter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { Rotation } from '../../../../utils/commons';
import { Transform } from '../../state/utils';
import { getChartRotationSelector } from '../../../../state/selectors/get_chart_rotation';
import { computeChartDimensionsSelector } from '../../state/selectors/compute_chart_dimensions';
import { DEFAULT_HIGHLIGHT_PADDING } from '../../rendering/rendering';

interface HighlighterProps {
initialized: boolean;
Expand Down Expand Up @@ -64,10 +65,11 @@ class HighlighterComponent extends React.Component<HighlighterProps> {
key={i}
cx={x + geom.transform.x}
cy={y}
r={geom.radius}
r={geom.radius + DEFAULT_HIGHLIGHT_PADDING}
stroke={color}
strokeWidth={4}
fill="transparent"
clipPath={geom.value.dot !== null ? `url(#${clipPathId})` : undefined}
/>
);
}
Expand Down
Loading