mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
Color: fix alpha calculation < 16/255 and State-timeline threshold alpha (#35911)
This commit is contained in:
parent
81dce0716b
commit
f78452be30
@ -32,6 +32,7 @@ import { getFrameDisplayName } from './fieldState';
|
||||
import { getTimeField } from '../dataframe/processDataFrame';
|
||||
import { mapInternalLinkToExplore } from '../utils/dataLinks';
|
||||
import { getTemplateProxyForField } from './templateProxies';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
interface OverrideProps {
|
||||
match: FieldMatcher;
|
||||
@ -204,11 +205,17 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
|
||||
});
|
||||
}
|
||||
|
||||
// this is a significant optimization for streaming, where we currently re-process all values in the buffer on ech update
|
||||
// via field.display(value). this can potentially be removed once we...
|
||||
// 1. process data packets incrementally and/if cache the results in the streaming datafame (maybe by buffer index)
|
||||
// 2. have the ability to selectively get display color or text (but not always both, which are each quite expensive)
|
||||
// 3. sufficently optimize text formating and threshold color determinitation
|
||||
function cachingDisplayProcessor(disp: DisplayProcessor, maxCacheSize = 2500): DisplayProcessor {
|
||||
const cache = new Map<any, DisplayValue>();
|
||||
|
||||
return (value: any) => {
|
||||
let v = cache.get(value);
|
||||
|
||||
if (!v) {
|
||||
// Don't grow too big
|
||||
if (cache.size === maxCacheSize) {
|
||||
@ -216,8 +223,17 @@ function cachingDisplayProcessor(disp: DisplayProcessor, maxCacheSize = 2500): D
|
||||
}
|
||||
|
||||
v = disp(value);
|
||||
|
||||
// convert to hex6 or hex8 so downstream we can cheaply test for alpha (and set new alpha)
|
||||
// via a simple length check (in colorManipulator) rather using slow parsing via tinycolor
|
||||
if (v.color && v.color[0] !== '#') {
|
||||
let color = tinycolor(v.color);
|
||||
v.color = color.getAlpha() < 1 ? color.toHex8String() : color.toHexString();
|
||||
}
|
||||
|
||||
cache.set(value, v);
|
||||
}
|
||||
|
||||
return v;
|
||||
};
|
||||
}
|
||||
|
@ -279,6 +279,10 @@ describe('utils/colorManipulator', () => {
|
||||
expect(alpha('hsla(0, 100%, 50%, 0.2)', 0.5)).toEqual('hsla(0, 100%, 50%, 0.5)');
|
||||
});
|
||||
|
||||
it('converts an rgb hex color with the alpha value provided', () => {
|
||||
expect(alpha('#FFFFFF', 0)).toEqual('#FFFFFF00');
|
||||
});
|
||||
|
||||
it('throw on invalid colors', () => {
|
||||
expect(() => {
|
||||
alpha('white', 0.4);
|
||||
|
@ -248,7 +248,12 @@ export function alpha(color: string, value: number) {
|
||||
color = color.substring(0, 7);
|
||||
}
|
||||
|
||||
return color + Math.round(value * 255).toString(16);
|
||||
return (
|
||||
color +
|
||||
Math.round(value * 255)
|
||||
.toString(16)
|
||||
.padStart(2, '0')
|
||||
);
|
||||
}
|
||||
// rgb(, hsl(
|
||||
else if (color[3] === '(') {
|
||||
|
@ -547,6 +547,12 @@ export function getConfig(opts: TimelineCoreOptions) {
|
||||
}
|
||||
|
||||
function getFillColor(fieldConfig: TimelineFieldConfig, color: string) {
|
||||
// if #rgba with pre-existing alpha. ignore fieldConfig.fillOpacity
|
||||
// e.g. thresholds with opacity
|
||||
if (color[0] === '#' && color.length === 9) {
|
||||
return color;
|
||||
}
|
||||
|
||||
const opacityPercent = (fieldConfig.fillOpacity ?? 100) / 100;
|
||||
return alpha(color, opacityPercent);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user