From be1fb3de28b62731b0d972b922e469ebc8c8b36f Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Wed, 14 Jul 2021 14:21:20 +0200 Subject: [PATCH] feat(xy): hide labels that protrude the bar geometry (#1233) The overflowConstraints prop now replaces the existing BarSeries.displayValueSettings.hideClippedValue prop extending the existing feature with the ability to hide labels that protrude the bar geometry. fix #1234 BREAKING CHANGE: an API change is introduced: `hideClippedValue` is removed in favor of `overflowConstraints?: Array;`. The array can contain one or multiple overflow constraints enumerated as `LabelOverflowConstraint` --- ...ue-label-visually-looks-correct-1-snap.png | Bin 26320 -> 23381 bytes ...-geometry-and-chart-area-values-1-snap.png | Bin 0 -> 21878 bytes integration/tests/bar_stories.test.ts | 5 ++ packages/charts/api/charts.api.md | 12 ++- .../xy_chart/renderer/canvas/values/bar.ts | 23 +++-- .../chart_types/xy_chart/rendering/bars.ts | 28 +++---- .../src/chart_types/xy_chart/utils/specs.ts | 41 +++++++-- packages/charts/src/utils/geometry.ts | 7 +- stories/bar/2_label_value.tsx | 79 +++++++++++------- stories/bar/51_label_value_advanced.tsx | 24 +++++- 10 files changed, 155 insertions(+), 64 deletions(-) create mode 100644 integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-value-labels-positioning-clip-both-geometry-and-chart-area-values-1-snap.png diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-value-label-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-bar-chart-with-value-label-visually-looks-correct-1-snap.png index e2ac14c40657ee090cc7ed45bafdc4f91288663a..b56f46aa3a9ee98f31f0a1ee71aabf9d9115868a 100644 GIT binary patch literal 23381 zcmcG$1yoe+`Zhj*f=Y=hb=^DU4`o^W8+UF%AP{_cIjQFm2<93D zf?;+I8+^0gXuJXbU^qUPeF7=yqXPeP7a}k9_=Q`_=Cr%li{X=wJ(yKu9&gOsyqk}% z={@1Qb}ffo>!aBt`}mwcHlBYQCeE#uY{bU9_PKA@!9G1rPZ2_BN#4DA?Jhlf({C9Y zy&jC-WNK1jOIqaPi5!j-*GU&C@UoiIM$dRGHxz76^?6Oj?{IR}1jY%P{$PupG z9zoq5M!^fo$<19%N1e0q^YbV4nlLM;bat_%Q#sVb;D&1hUp~ag6O)igKYonS)zt;b z)2fPonfpqgi@XyCV_{**R_kC!kJaJfX{}s^I-6puaO`xAtE#H%V1e!aQWuqD4>unl z-!5DNmH0_AC^|ZNfFrB2lDu%VyVm{S9y|M&qN4Yf1yz9)6B@4yb$X|&9L;TPO!_}d zhmmt*hPDkPw-BQ*Z|%Fd?)EJTimtgPf9~W-RQ;UY!-p#ghLGU!a3)sPkkixC_Xi43 zpOW*M;6Yx$e*NO*%l?6ZC+6m?LPA37`L8xzL?|dItfs5W;5dxv0q?W_a*vv!I6K

~x=`5MmY{gVtaI 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 diff --git a/integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-value-labels-positioning-clip-both-geometry-and-chart-area-values-1-snap.png b/integration/tests/__image_snapshots__/bar-stories-test-ts-bar-series-stories-value-labels-positioning-clip-both-geometry-and-chart-area-values-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..54e4b04973fa218834587fe49a5be9de41ab093a GIT binary patch literal 21878 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 { }); }); }); + it('clip both geometry and chart area values', async () => { + await common.expectChartAtUrlToMatchScreenshot( + 'http://localhost:9001/?path=/story/bar-chart--with-value-label&knob-show single series=&knob-show value label=true&knob-alternating value label=&knob-contain value label within bar element=&knob-hide label if overflows chart edges=true&knob-hide label if overflows bar geometry=true&knob-debug=&knob-value font size=11&knob-value color=%23000&knob-offsetX=0&knob-offsetY=10&knob-data volume size=s&knob-split series=&knob-stacked series=&knob-chartRotation=0&knob-legend=right', + ); + }); }); describe('functional accessors', () => { diff --git a/packages/charts/api/charts.api.md b/packages/charts/api/charts.api.md index 4785c671a9..e862bfb14a 100644 --- a/packages/charts/api/charts.api.md +++ b/packages/charts/api/charts.api.md @@ -645,9 +645,10 @@ export type Direction = $Values; // @public (undocumented) export interface DisplayValueSpec { - hideClippedValue?: boolean; isAlternatingValueLabel?: boolean; + // @deprecated isValueContainedInElement?: boolean; + overflowConstraints?: Array; showValueLabel?: boolean; valueFormatter?: TickFormatter; } @@ -1093,6 +1094,15 @@ export type Key = CategoryKey; // @public (undocumented) export type LabelAccessor = (value: PrimitiveValue) => string; +// @public (undocumented) +export const LabelOverflowConstraint: Readonly<{ + BarGeometry: "barGeometry"; + ChartEdges: "chartEdges"; +}>; + +// @public (undocumented) +export type LabelOverflowConstraint = $Values; + // @public (undocumented) export interface LayerValue { depth: number; diff --git a/packages/charts/src/chart_types/xy_chart/renderer/canvas/values/bar.ts b/packages/charts/src/chart_types/xy_chart/renderer/canvas/values/bar.ts index 9c3f30e6cc..f830839487 100644 --- a/packages/charts/src/chart_types/xy_chart/renderer/canvas/values/bar.ts +++ b/packages/charts/src/chart_types/xy_chart/renderer/canvas/values/bar.ts @@ -15,6 +15,7 @@ import { Dimensions } from '../../../../../utils/dimensions'; import { BarGeometry } from '../../../../../utils/geometry'; import { Point } from '../../../../../utils/point'; import { Theme, TextAlignment } from '../../../../../utils/themes/theme'; +import { LabelOverflowConstraint } from '../../../utils/specs'; import { renderText, wrapLines } from '../primitives/text'; import { renderDebugRect } from '../utils/debug'; import { withPanelTransform } from '../utils/panel_transform'; @@ -45,7 +46,7 @@ export function renderBarValues(ctx: CanvasRenderingContext2D, props: BarValuesP if (!displayValue) { continue; } - const { text, fontSize, fontScale } = displayValue; + const { text, fontSize, fontScale, overflowConstraints, isValueContainedInElement } = displayValue; let textLines = { lines: [text], width: displayValue.width, @@ -60,7 +61,7 @@ export function renderBarValues(ctx: CanvasRenderingContext2D, props: BarValuesP textOpacity: 1, }; - const { x, y, align, baseline, rect } = positionText( + const { x, y, align, baseline, rect, overflow } = positionText( bars[i], displayValue, rotation, @@ -68,15 +69,20 @@ export function renderBarValues(ctx: CanvasRenderingContext2D, props: BarValuesP alignment, ); - if (displayValue.isValueContainedInElement) { + if (isValueContainedInElement) { const width = rotation === 0 || rotation === 180 ? bars[i].width : bars[i].height; textLines = wrapLines(ctx, textLines.lines[0], font, fontSize, width, 100); } - if (displayValue.hideClippedValue && isOverflow(rect, renderingArea, rotation)) { + if (overflowConstraints.has(LabelOverflowConstraint.ChartEdges) && isOverflow(rect, renderingArea, rotation)) { + continue; + } + if (overflowConstraints.has(LabelOverflowConstraint.BarGeometry) && overflow) { continue; } if (debug) { - renderDebugRect(ctx, rect); + withPanelTransform(ctx, panel, rotation, renderingArea, (ctx) => { + renderDebugRect(ctx, rect); + }); } const { width, height } = textLines; const linesLength = textLines.lines.length; @@ -108,6 +114,7 @@ export function renderBarValues(ctx: CanvasRenderingContext2D, props: BarValuesP } } } + function repositionTextLine( origin: Point, chartRotation: Rotation, @@ -253,7 +260,7 @@ function positionText( chartRotation: Rotation, offsets: { offsetX: number; offsetY: number }, alignment?: TextAlignment, -): { x: number; y: number; align: TextAlign; baseline: TextBaseline; rect: Rect } { +): { x: number; y: number; align: TextAlign; baseline: TextBaseline; rect: Rect; overflow: boolean } { const { offsetX, offsetY } = offsets; const { alignmentOffsetX, alignmentOffsetY } = computeAlignmentOffset(geom, valueBox, chartRotation, alignment); @@ -273,6 +280,7 @@ function positionText( width: valueBox.width, height: valueBox.height, }, + overflow: valueBox.width > geom.width || valueBox.height > geom.height, }; } case CHART_DIRECTION.RightToLeft: { @@ -289,6 +297,7 @@ function positionText( width: valueBox.height, height: valueBox.width, }, + overflow: valueBox.height > geom.width || valueBox.width > geom.height, }; } case CHART_DIRECTION.LeftToRight: { @@ -305,6 +314,7 @@ function positionText( width: valueBox.height, height: valueBox.width, }, + overflow: valueBox.height > geom.width || valueBox.width > geom.height, }; } case CHART_DIRECTION.BottomUp: @@ -322,6 +332,7 @@ function positionText( width: valueBox.width, height: valueBox.height, }, + overflow: valueBox.width > geom.width || valueBox.height > geom.height, }; } } diff --git a/packages/charts/src/chart_types/xy_chart/rendering/bars.ts b/packages/charts/src/chart_types/xy_chart/rendering/bars.ts index 0c8af49ffb..09a27afd98 100644 --- a/packages/charts/src/chart_types/xy_chart/rendering/bars.ts +++ b/packages/charts/src/chart_types/xy_chart/rendering/bars.ts @@ -15,7 +15,7 @@ import { BandedAccessorType, BarGeometry } from '../../../utils/geometry'; import { BarSeriesStyle, DisplayValueStyle } from '../../../utils/themes/theme'; import { IndexedGeometryMap } from '../utils/indexed_geometry_map'; import { DataSeries, DataSeriesDatum, XYChartSeriesIdentifier } from '../utils/series'; -import { BarStyleAccessor, DisplayValueSpec, StackMode } from '../utils/specs'; +import { BarStyleAccessor, DisplayValueSpec, LabelOverflowConstraint, StackMode } from '../utils/specs'; /** @internal */ export function renderBars( @@ -115,19 +115,14 @@ export function renderBars( const x = xScaled + xScale.bandwidth * orderIndex + xScale.bandwidth / 2 - width / 2; const originalY1Value = stackMode === StackMode.Percentage ? y1 - (y0 ?? 0) : initialY1; - const formattedDisplayValue = - displayValueSettings && displayValueSettings.valueFormatter - ? displayValueSettings.valueFormatter(originalY1Value) - : undefined; + const formattedDisplayValue = displayValueSettings?.valueFormatter?.(originalY1Value); // only show displayValue for even bars if showOverlappingValue const displayValueText = - displayValueSettings && displayValueSettings.isAlternatingValueLabel && barGeometries.length % 2 - ? undefined - : formattedDisplayValue; + displayValueSettings?.isAlternatingValueLabel && barGeometries.length % 2 ? undefined : formattedDisplayValue; const { displayValueWidth, fixedFontScale } = computeBoxWidth( - displayValueText || '', + displayValueText ?? '', { padding, fontSize, fontFamily, bboxCalculator, width }, displayValueSettings, ); @@ -143,21 +138,26 @@ export function renderBars( fixedFontScale, fontSize, ); + const overflowConstraints: Set = new Set( + displayValueSettings?.overflowConstraints ?? [ + LabelOverflowConstraint.ChartEdges, + LabelOverflowConstraint.BarGeometry, + ], + ); - const hideClippedValue = displayValueSettings ? displayValueSettings.hideClippedValue : undefined; // Based on rotation scale the width of the text box const bboxWidthFactor = isHorizontalRotation ? textScalingFactor : 1; - const displayValue = - displayValueSettings && displayValueSettings.showValueLabel + const displayValue: BarGeometry['displayValue'] | undefined = + displayValueText && displayValueSettings?.showValueLabel ? { fontScale: textScalingFactor, fontSize: fixedFontScale, text: displayValueText, width: bboxWidthFactor * displayValueWidth, height: textScalingFactor * fixedFontScale, - hideClippedValue, - isValueContainedInElement: displayValueSettings.isValueContainedInElement, + overflowConstraints, + isValueContainedInElement: displayValueSettings?.isValueContainedInElement ?? false, } : undefined; diff --git a/packages/charts/src/chart_types/xy_chart/utils/specs.ts b/packages/charts/src/chart_types/xy_chart/utils/specs.ts index d53a95ff77..dc5a27a491 100644 --- a/packages/charts/src/chart_types/xy_chart/utils/specs.ts +++ b/packages/charts/src/chart_types/xy_chart/utils/specs.ts @@ -373,18 +373,47 @@ export type YDomainRange = YDomainBase & DomainRange & LogScaleOptions; /** @public */ export type CustomXDomain = (DomainRange & Pick) | OrdinalDomain; +/** @public */ +export const LabelOverflowConstraint = Object.freeze({ + BarGeometry: 'barGeometry' as const, + ChartEdges: 'chartEdges' as const, +}); + +/** @public */ +export type LabelOverflowConstraint = $Values; + /** @public */ export interface DisplayValueSpec { - /** Show value label in chart element */ + /** + * Show value label in chart element + * @defaultValue false + */ showValueLabel?: boolean; - /** If value labels are shown, skips every other label */ + /** + * If value labels are shown, skips every other label + * @defaultValue false + */ isAlternatingValueLabel?: boolean; - /** Function for formatting values; will use axis tickFormatter if none specified */ + /** + * Function for formatting values; will use axis tickFormatter if none specified + * @defaultValue false + */ valueFormatter?: TickFormatter; - /** If true will contain value label within element, else dimensions are computed based on value */ + /** + * If true will contain value label within element, else dimensions are computed based on value + * @deprecated This feature is deprecated and will be removed. Wrapping numbers into multiple lines + * is not considered a good practice. + * @defaultValue false + */ isValueContainedInElement?: boolean; - /** If true will hide values that are clipped at chart edges */ - hideClippedValue?: boolean; + + /** + * An option to hide the value label on certain conditions: + * - `barGeometry` the label is not rendered if the width/height overflows the associated bar geometry, + * - `chartEdges` the label is not rendered if it overflows the chart projection area. + * @defaultValue ['barGeometry', 'chartEdges'] + */ + overflowConstraints?: Array; } /** @public */ diff --git a/packages/charts/src/utils/geometry.ts b/packages/charts/src/utils/geometry.ts index 848b2d5a00..f9382ff8be 100644 --- a/packages/charts/src/utils/geometry.ts +++ b/packages/charts/src/utils/geometry.ts @@ -9,6 +9,7 @@ import { $Values } from 'utility-types'; import { XYChartSeriesIdentifier } from '../chart_types/xy_chart/utils/series'; +import { LabelOverflowConstraint } from '../chart_types/xy_chart/utils/specs'; import { Fill, Stroke } from '../geoms/types'; import { Color } from './common'; import { Dimensions } from './dimensions'; @@ -91,13 +92,13 @@ export interface BarGeometry { }; color: Color; displayValue?: { - fontScale?: number; + fontScale: number; fontSize: number; text: any; width: number; height: number; - hideClippedValue?: boolean; - isValueContainedInElement?: boolean; + overflowConstraints: Set; + isValueContainedInElement: boolean; }; seriesIdentifier: XYChartSeriesIdentifier; value: GeometryValue; diff --git a/stories/bar/2_label_value.tsx b/stories/bar/2_label_value.tsx index 5f6feac102..755841897f 100644 --- a/stories/bar/2_label_value.tsx +++ b/stories/bar/2_label_value.tsx @@ -9,7 +9,16 @@ import { boolean, color, number, select } from '@storybook/addon-knobs'; import React from 'react'; -import { Axis, BarSeries, Chart, Position, ScaleType, Settings } from '../../packages/charts/src'; +import { + Axis, + BarSeries, + Chart, + DisplayValueSpec, + LabelOverflowConstraint, + Position, + ScaleType, + Settings, +} from '../../packages/charts/src'; import { SeededDataGenerator } from '../../packages/charts/src/mocks/utils'; import { getChartRotationKnob, getPositionKnob } from '../utils/knobs'; @@ -17,9 +26,9 @@ const dataGen = new SeededDataGenerator(); function generateDataWithAdditional(num: number) { return [...dataGen.generateSimpleSeries(num), { x: num, y: 0.25, g: 0 }, { x: num + 1, y: 8, g: 0 }]; } -const frozenDataSmallVolume = generateDataWithAdditional(10); -const frozenDataMediumVolume = generateDataWithAdditional(50); -const frozenDataHighVolume = generateDataWithAdditional(1500); +const frozenDataSmallVolume = generateDataWithAdditional(5); +const frozenDataMediumVolume = generateDataWithAdditional(30); +const frozenDataHighVolume = generateDataWithAdditional(500); const frozenData: { [key: string]: any[] } = { s: frozenDataSmallVolume, @@ -28,16 +37,24 @@ const frozenData: { [key: string]: any[] } = { }; export const Example = () => { + const singleSeries = boolean('show single series', false); const showValueLabel = boolean('show value label', true); const isAlternatingValueLabel = boolean('alternating value label', false); const isValueContainedInElement = boolean('contain value label within bar element', false); - const hideClippedValue = boolean('hide clipped value', false); - + const overflowChartEdges = boolean('hide label if overflows chart edges', false); + const overflowBarGeometry = boolean('hide label if overflows bar geometry', false); + const overflowConstraints: DisplayValueSpec['overflowConstraints'] = []; + if (overflowChartEdges) { + overflowConstraints.push(LabelOverflowConstraint.ChartEdges); + } + if (overflowBarGeometry) { + overflowConstraints.push(LabelOverflowConstraint.BarGeometry); + } const displayValueSettings = { showValueLabel, isAlternatingValueLabel, isValueContainedInElement, - hideClippedValue, + overflowConstraints, }; const debug = boolean('debug', false); @@ -45,13 +62,13 @@ export const Example = () => { const theme = { barSeriesStyle: { displayValue: { - fontSize: number('value font size', 10), + fontSize: Number(number('value font size', 10)), fontFamily: "'Open Sans', Helvetica, Arial, sans-serif", fontStyle: 'normal', padding: 0, fill: color('value color', '#000'), - offsetX: number('offsetX', 0), - offsetY: number('offsetY', 0), + offsetX: Number(number('offsetX', 0)), + offsetY: Number(number('offsetY', 0)), }, }, }; @@ -95,26 +112,28 @@ export const Example = () => { stackAccessors={stackAccessors} data={data} /> - + {!singleSeries && ( + + )} ); }; diff --git a/stories/bar/51_label_value_advanced.tsx b/stories/bar/51_label_value_advanced.tsx index b66bbfd306..761161d2c8 100644 --- a/stories/bar/51_label_value_advanced.tsx +++ b/stories/bar/51_label_value_advanced.tsx @@ -9,7 +9,16 @@ import { boolean, color, number, select } from '@storybook/addon-knobs'; import React from 'react'; -import { Axis, BarSeries, Chart, Position, ScaleType, Settings } from '../../packages/charts/src'; +import { + Axis, + BarSeries, + Chart, + DisplayValueSpec, + LabelOverflowConstraint, + Position, + ScaleType, + Settings, +} from '../../packages/charts/src'; import { SeededDataGenerator } from '../../packages/charts/src/mocks/utils'; import { getChartRotationKnob } from '../utils/knobs'; @@ -31,13 +40,20 @@ export const Example = () => { const showValueLabel = boolean('show value label', true); const isAlternatingValueLabel = boolean('alternating value label', false); const isValueContainedInElement = boolean('contain value label within bar element', false); - const hideClippedValue = boolean('hide clipped value', false); - + const overflowChartEdges = boolean('hide label if overflows chart edges', false); + const overflowBarGeometry = boolean('hide label if overflows bar geometry', false); + const overflowConstraints: DisplayValueSpec['overflowConstraints'] = []; + if (overflowChartEdges) { + overflowConstraints.push(LabelOverflowConstraint.ChartEdges); + } + if (overflowBarGeometry) { + overflowConstraints.push(LabelOverflowConstraint.BarGeometry); + } const displayValueSettings = { showValueLabel, isAlternatingValueLabel, isValueContainedInElement, - hideClippedValue, + overflowConstraints, }; const debug = boolean('debug', false);