From 79ec3ec54c35a046dbfec2e04a65badc77033dc7 Mon Sep 17 00:00:00 2001 From: Leon Sorokin Date: Fri, 21 Jan 2022 17:19:53 -0600 Subject: [PATCH] TimeSeries: prevent threshold line color from affecting grid lines (#44337) --- .../uPlot/config/UPlotThresholds.ts | 150 +++++++++--------- 1 file changed, 79 insertions(+), 71 deletions(-) diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts index 21029f98f07..a682824599f 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotThresholds.ts @@ -1,4 +1,4 @@ -import { GrafanaTheme2, ThresholdsConfig, ThresholdsMode } from '@grafana/data'; +import { GrafanaTheme2, Threshold, ThresholdsConfig, ThresholdsMode } from '@grafana/data'; import { GraphThresholdsStyleConfig, GraphTresholdsStyleMode } from '@grafana/schema'; import { getGradientRange, scaleGradient } from './gradientFills'; import tinycolor from 'tinycolor2'; @@ -16,9 +16,79 @@ export interface UPlotThresholdOptions { } export function getThresholdsDrawHook(options: UPlotThresholdOptions) { + function addLines(u: uPlot, steps: Threshold[], theme: GrafanaTheme2, xMin: number, xMax: number, yScaleKey: string) { + let ctx = u.ctx; + + // Thresholds below a transparent threshold is treated like "less than", and line drawn previous threshold + let transparentIndex = 0; + + for (let idx = 0; idx < steps.length; idx++) { + const step = steps[idx]; + if (step.color === 'transparent') { + transparentIndex = idx; + break; + } + } + + ctx.lineWidth = 2; + + // Ignore the base -Infinity threshold by always starting on index 1 + for (let idx = 1; idx < steps.length; idx++) { + const step = steps[idx]; + let color: tinycolor.Instance; + + // if we are below a transparent index treat this a less then threshold, use previous thresholds color + if (transparentIndex >= idx && idx > 0) { + color = tinycolor(theme.visualization.getColorByName(steps[idx - 1].color)); + } else { + color = tinycolor(theme.visualization.getColorByName(step.color)); + } + + // Unless alpha specififed set to default value + if (color.getAlpha() === 1) { + color.setAlpha(0.7); + } + + let x0 = Math.round(u.valToPos(xMin!, 'x', true)); + let y0 = Math.round(u.valToPos(step.value, yScaleKey, true)); + let x1 = Math.round(u.valToPos(xMax!, 'x', true)); + let y1 = Math.round(u.valToPos(step.value, yScaleKey, true)); + + ctx.beginPath(); + ctx.moveTo(x0, y0); + ctx.lineTo(x1, y1); + + ctx.strokeStyle = color.toString(); + ctx.stroke(); + } + } + + function addAreas(u: uPlot, steps: Threshold[], theme: GrafanaTheme2) { + let ctx = u.ctx; + + let grd = scaleGradient( + u, + u.series[1].scale!, + steps.map((step) => { + let color = tinycolor(theme.visualization.getColorByName(step.color)); + + if (color.getAlpha() === 1) { + color.setAlpha(0.15); + } + + return [step.value, color.toString()]; + }), + true + ); + + ctx.fillStyle = grd; + ctx.fillRect(u.bbox.left, u.bbox.top, u.bbox.width, u.bbox.height); + } + + const { scaleKey, thresholds, theme, config, hardMin, hardMax, softMin, softMax } = options; + return (u: uPlot) => { const ctx = u.ctx; - const { scaleKey, thresholds, theme, config, hardMin, hardMax, softMin, softMax } = options; const { min: xMin, max: xMax } = u.scales.x; const { min: yMin, max: yMax } = u.scales[scaleKey]; @@ -38,82 +108,20 @@ export function getThresholdsDrawHook(options: UPlotThresholdOptions) { })); } - function addLines() { - // Thresholds below a transparent threshold is treated like "less than", and line drawn previous threshold - let transparentIndex = 0; - - for (let idx = 0; idx < steps.length; idx++) { - const step = steps[idx]; - if (step.color === 'transparent') { - transparentIndex = idx; - break; - } - } - - // Ignore the base -Infinity threshold by always starting on index 1 - for (let idx = 1; idx < steps.length; idx++) { - const step = steps[idx]; - let color: tinycolor.Instance; - - // if we are below a transparent index treat this a less then threshold, use previous thresholds color - if (transparentIndex >= idx && idx > 0) { - color = tinycolor(theme.visualization.getColorByName(steps[idx - 1].color)); - } else { - color = tinycolor(theme.visualization.getColorByName(step.color)); - } - - // Unless alpha specififed set to default value - if (color.getAlpha() === 1) { - color.setAlpha(0.7); - } - - let x0 = Math.round(u.valToPos(xMin!, 'x', true)); - let y0 = Math.round(u.valToPos(step.value, scaleKey, true)); - let x1 = Math.round(u.valToPos(xMax!, 'x', true)); - let y1 = Math.round(u.valToPos(step.value, scaleKey, true)); - - ctx.beginPath(); - ctx.lineWidth = 2; - ctx.strokeStyle = color.toString(); - ctx.moveTo(x0, y0); - ctx.lineTo(x1, y1); - ctx.stroke(); - ctx.closePath(); - } - } - - function addAreas() { - let grd = scaleGradient( - u, - u.series[1].scale!, - steps.map((step) => { - let color = tinycolor(theme.visualization.getColorByName(step.color)); - - if (color.getAlpha() === 1) { - color.setAlpha(0.15); - } - - return [step.value, color.toString()]; - }), - true - ); - - ctx.save(); - ctx.fillStyle = grd; - ctx.fillRect(u.bbox.left, u.bbox.top, u.bbox.width, u.bbox.height); - ctx.restore(); - } + ctx.save(); switch (config.mode) { case GraphTresholdsStyleMode.Line: - addLines(); + addLines(u, steps, theme, xMin, xMax, scaleKey); break; case GraphTresholdsStyleMode.Area: - addAreas(); + addAreas(u, steps, theme); break; case GraphTresholdsStyleMode.LineAndArea: - addLines(); - addAreas(); + addAreas(u, steps, theme); + addLines(u, steps, theme, xMin, xMax, scaleKey); } + + ctx.restore(); }; }