diff --git a/packages/grafana-ui/src/components/Gauge/Gauge.test.tsx b/packages/grafana-ui/src/components/Gauge/Gauge.test.tsx index 0a337707c365..00037a9872c6 100644 --- a/packages/grafana-ui/src/components/Gauge/Gauge.test.tsx +++ b/packages/grafana-ui/src/components/Gauge/Gauge.test.tsx @@ -19,6 +19,9 @@ const field: FieldConfig = { mode: ThresholdsMode.Absolute, steps: [{ value: -Infinity, color: '#7EB26D' }], }, + custom: { + neeutral: 0, + }, }; const props: Props = { diff --git a/packages/grafana-ui/src/components/Gauge/Gauge.tsx b/packages/grafana-ui/src/components/Gauge/Gauge.tsx index 39e7a80808e0..1f54b72aff4b 100644 --- a/packages/grafana-ui/src/components/Gauge/Gauge.tsx +++ b/packages/grafana-ui/src/components/Gauge/Gauge.tsx @@ -98,6 +98,7 @@ export class Gauge extends PureComponent { gauge: { min, max, + neutralValue: field.custom?.neutral, background: { color: backgroundColor }, border: { color: null }, shadow: { show: false }, diff --git a/public/app/plugins/panel/gauge/module.tsx b/public/app/plugins/panel/gauge/module.tsx index 3a36fd460a2b..0910083e2310 100644 --- a/public/app/plugins/panel/gauge/module.tsx +++ b/public/app/plugins/panel/gauge/module.tsx @@ -9,11 +9,22 @@ import { PanelOptions, defaultPanelOptions } from './models.gen'; import { GaugeSuggestionsSupplier } from './suggestions'; export const plugin = new PanelPlugin(GaugePanel) - .useFieldConfig() + .useFieldConfig({ + useCustomConfig: (builder) => { + builder.addNumberInput({ + path: 'neutral', + name: 'Neutral', + description: 'Leave empty to use Min as neutral point', + category: ['Gauge'], + settings: { + placeholder: 'auto', + }, + }); + }, + }) .setPanelOptions((builder) => { addStandardDataReduceOptions(builder); addOrientationOption(builder); - builder .addBooleanSwitch({ path: 'showThresholdLabels', diff --git a/public/vendor/flot/jquery.flot.gauge.js b/public/vendor/flot/jquery.flot.gauge.js index 760354cecd4f..8c5c43a9213a 100644 --- a/public/vendor/flot/jquery.flot.gauge.js +++ b/public/vendor/flot/jquery.flot.gauge.js @@ -325,9 +325,9 @@ */ Gauge.prototype.drawGauge = function(gaugeOptionsi, layout, cellLayout, label, data) { - var blur = gaugeOptionsi.gauge.shadow.show ? gaugeOptionsi.gauge.shadow.blur : 0; - + var color = getColor(gaugeOptionsi, data); + var angles = calculateAnglesForGauge(gaugeOptionsi, layout, data); // draw gauge frame drawArcWithShadow( @@ -343,19 +343,74 @@ blur); // draw gauge - var c1 = getColor(gaugeOptionsi, data); - var a2 = calculateAngle(gaugeOptionsi, layout, data); drawArcWithShadow( cellLayout.cx, // center x cellLayout.cy, // center y layout.radius - 1, layout.width - 2, - toRad(gaugeOptionsi.gauge.startAngle), - toRad(a2), - c1, // line color + toRad(angles.a1), + toRad(angles.a2), + color, 1, // line width - c1, // fill color + color, // fill color blur); + + if(gaugeOptionsi.gauge.neutralValue != null) { + drawZeroMarker(gaugeOptionsi, layout, cellLayout, color); + } + } + + /** + * Calcualte the angles for the gauge, depending on if there are + * negative numbers or not. + * + * @method calculateAnglesForGauge + * @param {Object} gaugeOptionsi the options of the gauge + * @param {Number} data the value of the gauge + * @returns {Object} + */ + function calculateAnglesForGauge(gaugeOptionsi, layout, data) { + let angles = {}; + var neutral = gaugeOptionsi.gauge.neutralValue; + + if (neutral != null) { + if (data < neutral) { + angles.a1 = calculateAngle(gaugeOptionsi, layout, data); + angles.a2 = calculateAngle(gaugeOptionsi, layout, neutral); + } else { + angles.a1 = calculateAngle(gaugeOptionsi, layout, neutral); + angles.a2 = calculateAngle(gaugeOptionsi, layout, data); + } + } else { + angles.a1 = gaugeOptionsi.gauge.startAngle; + angles.a2 = calculateAngle(gaugeOptionsi, layout, data); + } + + return angles; + } + + /** + * Draw zero marker for Gauge with negative values + * + * @method drawZeroMarker + * @param {Object} gaugeOptionsi the options of the gauge + * @param {Object} layout the layout properties + * @param {Object} cellLayout the cell layout properties + * @param {String} color line color + */ + function drawZeroMarker(gaugeOptionsi, layout, cellLayout, color) { + var diff = (gaugeOptionsi.gauge.max - gaugeOptionsi.gauge.min) / 600; + + drawArc(context, + cellLayout.cx, + cellLayout.cy, + layout.radius - 2, + layout.width - 4, + toRad(calculateAngle(gaugeOptionsi, layout, gaugeOptionsi.gauge.neutralValue-diff)), + toRad(calculateAngle(gaugeOptionsi, layout, gaugeOptionsi.gauge.neutralValue+diff)), + color, + 2, + gaugeOptionsi.gauge.background.color); } /** @@ -529,6 +584,13 @@ drawThresholdValue(gaugeOptionsi, layout, cellLayout, i + "_" + j, threshold.value, a); } } + + var neutral = gaugeOptionsi.gauge.neutralValue; + if (neutral != null && + neutral>gaugeOptionsi.gauge.min && + neutral