diff --git a/src/chart_types/partition_chart/layout/config/config.ts b/src/chart_types/partition_chart/layout/config/config.ts index bd1aec205f..2d450e76b9 100644 --- a/src/chart_types/partition_chart/layout/config/config.ts +++ b/src/chart_types/partition_chart/layout/config/config.ts @@ -232,7 +232,7 @@ export const configMetadata = { }, // other - backgroundColor: { dflt: '#ffffff', type: 'color' }, + // backgroundColor: { dflt: '#ffffff', type: 'color' }, sectorLineWidth: { dflt: 1, min: 0, max: 4, type: 'number' }, sectorLineStroke: { dflt: 'white', type: 'string' }, colors: { dflt: 'turbo', type: 'palette', values: Object.keys(palettes) }, diff --git a/src/chart_types/partition_chart/layout/types/config_types.ts b/src/chart_types/partition_chart/layout/types/config_types.ts index 81ba72a196..29f71d68d9 100644 --- a/src/chart_types/partition_chart/layout/types/config_types.ts +++ b/src/chart_types/partition_chart/layout/types/config_types.ts @@ -90,6 +90,7 @@ export interface StaticConfig { backgroundColor: Color; sectorLineWidth: Pixels; sectorLineStroke: StrokeStyle; + containerBackgroundColor: string; } export type EasingFunction = (x: Ratio) => Ratio; diff --git a/src/chart_types/partition_chart/layout/utils/calcs.ts b/src/chart_types/partition_chart/layout/utils/calcs.ts index c1ca89e2ad..b083067653 100644 --- a/src/chart_types/partition_chart/layout/utils/calcs.ts +++ b/src/chart_types/partition_chart/layout/utils/calcs.ts @@ -59,6 +59,23 @@ function computeContrast(rgb1: string, rgb2: string) { return colorJS(rgb1).contrast(colorJS(rgb2)); } +/** If the user specifies the background of the container in which the chart will be on, we can use that color + * and make sure to provide optimal contrast + * https://stackoverflow.com/questions/10781953/determine-rgba-colour-received-by-combining-two-colours*/ +/** @internal */ +export function getBackgroundWithContainerColorFromUser(rgba1: string, rgba2: string): string { + // @ts-ignore + const [red1, green1, blue1, alpha1] = parseInt(rgba1.replace(/[^\d.,]/g, '').split(',')); + // @ts-ignore + const [red2, green2, blue2, alpha2] = parseInt(rgba2.replace(/[^\d.,]/g, '').split(',')); + const alpha = alpha1 + alpha2 * (1 - alpha1); + const red = (red2 * alpha2 + red1 * alpha1 * (1 - alpha2)) / alpha; + const green = (green2 * alpha2 + green1 * alpha1 * (1 - alpha2)) / alpha; + const blue = (blue2 * alpha2 + blue1 * alpha1 * (1 - alpha2)) / alpha; + + return `rgba(${red}, ${green}, ${blue}, ${alpha})`; +} + /** @internal */ export function colorIsDark(textColor: Color, bgColor: Color) { const currentContrast = computeContrast(textColor, bgColor); diff --git a/src/chart_types/partition_chart/layout/viewmodel/fill_text_layout.ts b/src/chart_types/partition_chart/layout/viewmodel/fill_text_layout.ts index 3c73c2933b..73613ef642 100644 --- a/src/chart_types/partition_chart/layout/viewmodel/fill_text_layout.ts +++ b/src/chart_types/partition_chart/layout/viewmodel/fill_text_layout.ts @@ -32,7 +32,7 @@ import { import { Box, Font, PartialFont, TextMeasure } from '../types/types'; import { conjunctiveConstraint } from '../circline_geometry'; import { Layer } from '../../specs/index'; -import { colorIsDark } from '../utils/calcs'; +import { colorIsDark, getBackgroundWithContainerColorFromUser } from '../utils/calcs'; import { ValueFormatter } from '../../../../utils/commons'; const INFINITY_RADIUS = 1e4; // far enough for a sub-2px precision on a 4k screen, good enough for text bounds; 64 bit floats still work well with it @@ -280,9 +280,13 @@ function fill( layer.fillLabel && layer.fillLabel.valueFont, ); - // need to compare the contrast from the shapeFillColor to the textColor and change the textColor if the contrast isn't enough - const shapeFillColor = node.fillColor; - const textColorWithContrast = colorIsDark(textColor, shapeFillColor); + // need to compare the contrast from the shapeFillColor and the background of the container to the textColor and change the textColor if the contrast isn't at least 4.5 + const sliceFillColor = node.fillColor; + const containerBackgroundColorFromUser = config.containerBackgroundColor; + const containerBackground = containerBackgroundColorFromUser + ? getBackgroundWithContainerColorFromUser(sliceFillColor, containerBackgroundColorFromUser) + : sliceFillColor; + const textColorWithContrast = colorIsDark(textColor, containerBackground); const sizeInvariantFont: Font = { fontStyle, fontVariant,