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

fix(renderer): stroke opacity #335

Merged
merged 8 commits into from
Aug 26, 2019
Merged
Show file tree
Hide file tree
Changes from 7 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
98 changes: 22 additions & 76 deletions .playground/playgroud.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
import React from 'react';

import {
Axis,
Chart,
getAxisId,
getSpecId,
niceTimeFormatter,
Position,
ScaleType,
Settings,
BarSeries,
LineAnnotation,
getAnnotationId,
AnnotationDomainTypes,
} from '../src';
import { Axis, Chart, getAxisId, getSpecId, niceTimeFormatter, Position, ScaleType, Settings, BarSeries } from '../src';
import { KIBANA_METRICS } from '../src/utils/data_samples/test_dataset_kibana';
import { CursorEvent } from '../src/specs/settings';
import { CursorUpdateListener } from '../src/chart_types/xy_chart/store/chart_state';
import { Icon } from '../src/components/icons/icon';

export class Playground extends React.Component {
ref1 = React.createRef<Chart>();
Expand All @@ -32,78 +18,38 @@ export class Playground extends React.Component {

render() {
return (
<>
{renderChart(
'1',
this.ref1,
KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 15),
this.onCursorUpdate,
true,
)}
{renderChart(
'2',
this.ref2,
KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15),
this.onCursorUpdate,
true,
)}
{renderChart('3', this.ref3, KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(15, 30), this.onCursorUpdate)}
</>
);
}
}

function renderChart(
key: string,
ref: React.RefObject<Chart>,
data: any,
onCursorUpdate?: CursorUpdateListener,
timeSeries: boolean = false,
) {
return (
<div key={key} className="chart">
<Chart ref={ref}>
<Settings
tooltip={{ type: 'vertical' }}
debug={false}
legendPosition={Position.Right}
showLegend={true}
onCursorUpdate={onCursorUpdate}
rotation={0}
/>
<Chart>
<Settings tooltip={{ type: 'vertical' }} debug={false} legendPosition={Position.Right} showLegend={true} />
<Axis
id={getAxisId('timestamp')}
title="timestamp"
position={Position.Bottom}
tickFormat={niceTimeFormatter([1555819200000, 1555905600000])}
/>
<Axis id={getAxisId('count')} title="count" position={Position.Left} tickFormat={(d) => d.toFixed(2)} />
<LineAnnotation
annotationId={getAnnotationId('annotation1')}
domainType={AnnotationDomainTypes.XDomain}
dataValues={[
{
dataValue: KIBANA_METRICS.metrics.kibana_os_load[1].data[5][0],
details: 'tooltip 1',
},
{
dataValue: KIBANA_METRICS.metrics.kibana_os_load[1].data[9][0],
details: 'tooltip 2',
},
]}
hideLinesTooltips={true}
marker={<Icon type="alert" />}
/>
<BarSeries
id={getSpecId('dataset A with long title')}
xScaleType={timeSeries ? ScaleType.Time : ScaleType.Linear}
id={getSpecId('dataset B')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={data}
data={KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15)}
xAccessor={0}
yAccessors={[1]}
stackAccessors={[0]}
barSeriesStyle={{
rectBorder: {
strokeOpacity: 1,
strokeWidth: 4,
stroke: 'blue',
visible: true,
},
rect: {
opacity: 0.25,
fill: 'red',
},
}}
/>
<BarSeries
id={getSpecId('dataset B')}
id={getSpecId('dataset C')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15)}
Expand All @@ -112,6 +58,6 @@ function renderChart(
stackAccessors={[0]}
/>
</Chart>
</div>
);
);
}
}
66 changes: 28 additions & 38 deletions src/chart_types/xy_chart/rendering/rendering.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { DEFAULT_GEOMETRY_STYLES } from '../../../utils/themes/theme_commons';
import { getSpecId } from '../../../utils/ids';
import {
BarGeometry,
Expand All @@ -8,7 +7,7 @@ import {
getStyleOverrides,
GeometryId,
} from './rendering';
import { BarSeriesStyle } from '../../../utils/themes/theme';
import { BarSeriesStyle, SharedGeometryStyle } from '../../../utils/themes/theme';
import { DataSeriesDatum } from '../utils/series';
import { RecursivePartial, mergePartial } from '../../../utils/commons';

Expand Down Expand Up @@ -116,67 +115,58 @@ describe('Rendering utils', () => {
},
};

const sharedThemeStyle = DEFAULT_GEOMETRY_STYLES;
const specOpacity = 0.66;

const defaultStyle = getGeometryStyle(geometryId, null, sharedThemeStyle);
const sharedThemeStyle: SharedGeometryStyle = {
default: {
opacity: 1,
},
highlighted: {
opacity: 0.5,
},
unhighlighted: {
opacity: 0.25,
},
};

// no highlighted elements
expect(defaultStyle).toEqual({ opacity: 1 });

const customDefaultStyle = getGeometryStyle(geometryId, null, sharedThemeStyle, specOpacity);

// no highlighted elements with custom spec opacity
expect(customDefaultStyle).toEqual({ opacity: 0.66 });

const highlightedStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedThemeStyle);
const defaultStyle = getGeometryStyle(geometryId, null, sharedThemeStyle);
expect(defaultStyle).toBe(sharedThemeStyle.default);

// should equal highlighted opacity
expect(highlightedStyle).toEqual({ opacity: 1 });

const unhighlightedStyle = getGeometryStyle(geometryId, unhighlightedLegendItem, sharedThemeStyle);
const highlightedStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedThemeStyle);
expect(highlightedStyle).toBe(sharedThemeStyle.highlighted);

// should equal unhighlighted opacity
expect(unhighlightedStyle).toEqual({ opacity: 0.25 });

const customHighlightedStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedThemeStyle, specOpacity);
const unhighlightedStyle = getGeometryStyle(geometryId, unhighlightedLegendItem, sharedThemeStyle);
expect(unhighlightedStyle).toBe(sharedThemeStyle.unhighlighted);

// should equal custom spec highlighted opacity
expect(customHighlightedStyle).toEqual({ opacity: 0.66 });

const customUnhighlightedStyle = getGeometryStyle(
geometryId,
unhighlightedLegendItem,
sharedThemeStyle,
specOpacity,
);
const customHighlightedStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedThemeStyle);
expect(customHighlightedStyle).toBe(sharedThemeStyle.highlighted);

// unhighlighted elements remain unchanged with custom opacity
expect(customUnhighlightedStyle).toEqual({ opacity: 0.25 });
const customUnhighlightedStyle = getGeometryStyle(geometryId, unhighlightedLegendItem, sharedThemeStyle);
expect(customUnhighlightedStyle).toBe(sharedThemeStyle.unhighlighted);

// has individual highlight
const hasIndividualHighlight = getGeometryStyle(geometryId, null, sharedThemeStyle, undefined, {
const hasIndividualHighlight = getGeometryStyle(geometryId, null, sharedThemeStyle, {
hasHighlight: true,
hasGeometryHover: true,
});

expect(hasIndividualHighlight).toEqual({ opacity: 1 });
expect(hasIndividualHighlight).toBe(sharedThemeStyle.highlighted);

// no highlight
const noHighlight = getGeometryStyle(geometryId, null, sharedThemeStyle, undefined, {
const noHighlight = getGeometryStyle(geometryId, null, sharedThemeStyle, {
hasHighlight: false,
hasGeometryHover: true,
});

expect(noHighlight).toEqual({ opacity: 0.25 });
expect(noHighlight).toBe(sharedThemeStyle.unhighlighted);

// no geometry hover
const noHover = getGeometryStyle(geometryId, null, sharedThemeStyle, undefined, {
const noHover = getGeometryStyle(geometryId, null, sharedThemeStyle, {
hasHighlight: true,
hasGeometryHover: false,
});

expect(noHover).toEqual({ opacity: 1 });
expect(noHover).toBe(sharedThemeStyle.highlighted);
});

describe('getStyleOverrides', () => {
Expand Down
25 changes: 11 additions & 14 deletions src/chart_types/xy_chart/rendering/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export interface GeometryValue {

/** Shared style properties for varies geometries */
export interface GeometryStyle {
/**
* Opacity multiplier
*
* if set to `0.5` all given opacities will be halfed
*/
opacity: number;
}

Expand Down Expand Up @@ -482,34 +487,26 @@ export function renderArea(
export function getGeometryStyle(
geometryId: GeometryId,
highlightedLegendItem: LegendItem | null,
sharedThemeStyle: SharedGeometryStyle,
specOpacity?: number,
sharedGeometryStyle: SharedGeometryStyle,
individualHighlight?: { [key: string]: boolean },
): GeometryStyle {
const sharedStyle =
specOpacity == null
? sharedThemeStyle
: {
...sharedThemeStyle,
highlighted: { opacity: specOpacity },
default: { opacity: specOpacity },
};
const { default: defaultStyles, highlighted, unhighlighted } = sharedGeometryStyle;

if (highlightedLegendItem != null) {
const isPartOfHighlightedSeries = belongsToDataSeries(geometryId, highlightedLegendItem.value);

return isPartOfHighlightedSeries ? sharedStyle.highlighted : sharedStyle.unhighlighted;
return isPartOfHighlightedSeries ? highlighted : unhighlighted;
}

if (individualHighlight) {
const { hasHighlight, hasGeometryHover } = individualHighlight;
if (!hasGeometryHover) {
return sharedStyle.highlighted;
return highlighted;
}
return hasHighlight ? sharedStyle.highlighted : sharedStyle.unhighlighted;
return hasHighlight ? highlighted : unhighlighted;
}

return sharedStyle.default;
return defaultStyles;
}

export function isPointOnGeometry(
Expand Down
21 changes: 4 additions & 17 deletions src/components/react_canvas/area_geometries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,7 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps,
areas.forEach((glyph, i) => {
const { seriesPointStyle, geometryId } = glyph;
if (seriesPointStyle.visible) {
const customOpacity = seriesPointStyle ? seriesPointStyle.opacity : undefined;
const geometryStyle = getGeometryStyle(
geometryId,
this.props.highlightedLegendItem,
sharedStyle,
customOpacity,
);
const geometryStyle = getGeometryStyle(geometryId, this.props.highlightedLegendItem, sharedStyle);
const pointStyleProps = buildPointStyleProps(glyph.color, seriesPointStyle, geometryStyle);
elements.push(...this.renderPoints(glyph.points, i, pointStyleProps, glyph.geometryId));
}
Expand All @@ -117,13 +111,7 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps,
acc.push(...this.renderAreaLines(glyph, i, sharedStyle, highlightedLegendItem));
}
if (seriesPointStyle.visible) {
const customOpacity = seriesPointStyle ? seriesPointStyle.opacity : undefined;
const geometryStyle = getGeometryStyle(
geometryId,
this.props.highlightedLegendItem,
sharedStyle,
customOpacity,
);
const geometryStyle = getGeometryStyle(geometryId, this.props.highlightedLegendItem, sharedStyle);
const pointStyleProps = buildPointStyleProps(glyph.color, seriesPointStyle, geometryStyle);
acc.push(...this.renderPoints(glyph.points, i, pointStyleProps, glyph.geometryId));
}
Expand All @@ -136,8 +124,7 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps,
highlightedLegendItem: LegendItem | null,
): JSX.Element => {
const { area, color, transform, geometryId, seriesAreaStyle } = glyph;
const customOpacity = seriesAreaStyle ? seriesAreaStyle.opacity : undefined;
const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle, customOpacity);
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} />;
Expand All @@ -149,7 +136,7 @@ export class AreaGeometries extends React.PureComponent<AreaGeometriesDataProps,
highlightedLegendItem: LegendItem | null,
): JSX.Element[] => {
const { lines, color, geometryId, transform, seriesAreaLineStyle } = glyph;
const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle, seriesAreaLineStyle.opacity);
const geometryStyle = getGeometryStyle(geometryId, highlightedLegendItem, sharedStyle);

return lines.map((linePath, lineIndex) => {
const key = getGeometryIdKey(geometryId, `area-line-${areaIndex}-${lineIndex}`);
Expand Down
Loading