diff --git a/public/app/plugins/panel/heatmap/color_legend.ts b/public/app/plugins/panel/heatmap/color_legend.ts index a86a498b723..a1c80629c7e 100644 --- a/public/app/plugins/panel/heatmap/color_legend.ts +++ b/public/app/plugins/panel/heatmap/color_legend.ts @@ -69,10 +69,11 @@ coreModule.directive('heatmapLegend', () => { function render() { clearLegend(elem); if (!_.isEmpty(ctrl.data) && !_.isEmpty(ctrl.data.cards)) { - const rangeFrom = 0; - const rangeTo = ctrl.data.cardStats.max; - const maxValue = panel.color.max || rangeTo; - const minValue = panel.color.min || 0; + const cardStats = ctrl.data.cardStats; + const rangeFrom = _.isNil(panel.color.min) ? Math.min(cardStats.min, 0) : panel.color.min; + const rangeTo = _.isNil(panel.color.max) ? cardStats.max : panel.color.max; + const maxValue = cardStats.max; + const minValue = cardStats.min; if (panel.color.mode === 'spectrum') { const colorScheme = _.find(ctrl.colorSchemes, { @@ -110,7 +111,7 @@ function drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minVal .data(valuesRange) .enter() .append('rect') - .attr('x', d => Math.round(d * widthFactor)) + .attr('x', d => Math.round((d - rangeFrom) * widthFactor)) .attr('y', 0) .attr('width', Math.round(rangeStep * widthFactor + 1)) // Overlap rectangles to prevent gaps .attr('height', legendHeight) @@ -141,7 +142,7 @@ function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue .data(valuesRange) .enter() .append('rect') - .attr('x', d => Math.round(d * widthFactor)) + .attr('x', d => Math.round((d - rangeFrom) * widthFactor)) .attr('y', 0) .attr('width', Math.round(rangeStep * widthFactor)) .attr('height', legendHeight) @@ -162,10 +163,10 @@ function drawLegendValues(elem, rangeFrom, rangeTo, maxValue, minValue, legendWi const legendValueScale = d3 .scaleLinear() - .domain([0, rangeTo]) + .domain([rangeFrom, rangeTo]) .range([0, legendWidth]); - const ticks = buildLegendTicks(0, rangeTo, maxValue, minValue); + const ticks = buildLegendTicks(rangeFrom, rangeTo, maxValue, minValue); const xAxis = d3 .axisBottom(legendValueScale) .tickValues(ticks) @@ -286,11 +287,12 @@ function getSvgElemHeight(elem) { function buildLegendTicks(rangeFrom, rangeTo, maxValue, minValue) { const range = rangeTo - rangeFrom; const tickStepSize = tickStep(rangeFrom, rangeTo, 3); - const ticksNum = Math.round(range / tickStepSize); + const ticksNum = Math.ceil(range / tickStepSize); + const firstTick = getFirstCloseTick(rangeFrom, tickStepSize); let ticks = []; for (let i = 0; i < ticksNum; i++) { - const current = tickStepSize * i; + const current = firstTick + tickStepSize * i; // Add user-defined min and max if it had been set if (isValueCloseTo(minValue, current, tickStepSize)) { ticks.push(minValue); @@ -304,7 +306,7 @@ function buildLegendTicks(rangeFrom, rangeTo, maxValue, minValue) { } else if (maxValue < current) { ticks.push(maxValue); } - ticks.push(tickStepSize * i); + ticks.push(current); } if (!isValueCloseTo(maxValue, rangeTo, tickStepSize)) { ticks.push(maxValue); @@ -318,3 +320,10 @@ function isValueCloseTo(val, valueTo, step) { const diff = Math.abs(val - valueTo); return diff < step * 0.3; } + +function getFirstCloseTick(minValue, step) { + if (minValue < 0) { + return Math.floor(minValue / step) * step; + } + return 0; +} diff --git a/public/app/plugins/panel/heatmap/rendering.ts b/public/app/plugins/panel/heatmap/rendering.ts index 59d704f0d55..702704b1ada 100644 --- a/public/app/plugins/panel/heatmap/rendering.ts +++ b/public/app/plugins/panel/heatmap/rendering.ts @@ -524,14 +524,16 @@ export class HeatmapRenderer { } const cardsData = this.data.cards; - const maxValueAuto = this.data.cardStats.max; - const maxValue = this.panel.color.max || maxValueAuto; - const minValue = this.panel.color.min || 0; + const cardStats = this.data.cardStats; + const maxValueAuto = cardStats.max; + const minValueAuto = Math.min(cardStats.min, 0); + const maxValue = _.isNil(this.panel.color.max) ? maxValueAuto : this.panel.color.max; + const minValue = _.isNil(this.panel.color.min) ? minValueAuto : this.panel.color.min; const colorScheme = _.find(this.ctrl.colorSchemes, { value: this.panel.color.colorScheme, }); this.colorScale = getColorScale(colorScheme, contextSrv.user.lightTheme, maxValue, minValue); - this.opacityScale = getOpacityScale(this.panel.color, maxValue); + this.opacityScale = getOpacityScale(this.panel.color, maxValue, minValue); this.setCardSize(); let cards = this.heatmap.selectAll('.heatmap-card').data(cardsData);