|
|
@@ -7,6 +7,10 @@ import {contextSrv} from 'app/core/core';
|
|
|
import {tickStep} from 'app/core/utils/ticks';
|
|
|
|
|
|
let module = angular.module('grafana.directives');
|
|
|
+
|
|
|
+/**
|
|
|
+ * Color legend for heatmap editor.
|
|
|
+ */
|
|
|
module.directive('colorLegend', function() {
|
|
|
return {
|
|
|
restrict: 'E',
|
|
|
@@ -38,6 +42,9 @@ module.directive('colorLegend', function() {
|
|
|
};
|
|
|
});
|
|
|
|
|
|
+/**
|
|
|
+ * Heatmap legend with scale values.
|
|
|
+ */
|
|
|
module.directive('heatmapLegend', function() {
|
|
|
return {
|
|
|
restrict: 'E',
|
|
|
@@ -54,19 +61,14 @@ module.directive('heatmapLegend', function() {
|
|
|
function render() {
|
|
|
clearLegend(elem);
|
|
|
if (!_.isEmpty(ctrl.data) && !_.isEmpty(ctrl.data.cards)) {
|
|
|
- let legendElem = $(elem).find('svg');
|
|
|
- let legendWidth = Math.floor(legendElem.outerWidth());
|
|
|
-
|
|
|
- // let maxValue = ctrl.data.cardStats.max || legendWidth;
|
|
|
- let rangeFrom = ctrl.data.cardStats.min;
|
|
|
+ let rangeFrom = 0;
|
|
|
let rangeTo = ctrl.data.cardStats.max;
|
|
|
let maxValue = panel.color.max || rangeTo;
|
|
|
let minValue = panel.color.min || 0;
|
|
|
|
|
|
if (panel.color.mode === 'spectrum') {
|
|
|
let colorScheme = _.find(ctrl.colorSchemes, {value: panel.color.colorScheme});
|
|
|
- let colorScale = getColorScale(colorScheme, maxValue, minValue);
|
|
|
- drawColorLegend(elem, colorScale, rangeFrom, rangeTo, maxValue, minValue);
|
|
|
+ drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minValue);
|
|
|
} else if (panel.color.mode === 'opacity') {
|
|
|
let colorOptions = panel.color;
|
|
|
drawOpacityLegend(elem, colorOptions, rangeFrom, rangeTo, maxValue, minValue);
|
|
|
@@ -77,8 +79,9 @@ module.directive('heatmapLegend', function() {
|
|
|
};
|
|
|
});
|
|
|
|
|
|
-function drawColorLegend(elem, colorScale, rangeFrom, rangeTo, maxValue, minValue) {
|
|
|
+function drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minValue) {
|
|
|
let legendElem = $(elem).find('svg');
|
|
|
+ let legend = d3.select(legendElem.get(0));
|
|
|
clearLegend(elem);
|
|
|
|
|
|
let legendWidth = Math.floor(legendElem.outerWidth()) - 30;
|
|
|
@@ -91,10 +94,10 @@ function drawColorLegend(elem, colorScale, rangeFrom, rangeTo, maxValue, minValu
|
|
|
let widthFactor = legendWidth / (rangeTo - rangeFrom);
|
|
|
let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
|
|
|
|
|
|
- let legend = d3.select(legendElem.get(0));
|
|
|
- var legendRects = legend.selectAll(".heatmap-color-legend-rect").data(valuesRange);
|
|
|
-
|
|
|
- legendRects.enter().append("rect")
|
|
|
+ let colorScale = getColorScale(colorScheme, maxValue, minValue);
|
|
|
+ legend.selectAll(".heatmap-color-legend-rect")
|
|
|
+ .data(valuesRange)
|
|
|
+ .enter().append("rect")
|
|
|
.attr("x", d => d * widthFactor)
|
|
|
.attr("y", 0)
|
|
|
.attr("width", rangeStep * widthFactor + 1) // Overlap rectangles to prevent gaps
|
|
|
@@ -107,6 +110,7 @@ function drawColorLegend(elem, colorScale, rangeFrom, rangeTo, maxValue, minValu
|
|
|
|
|
|
function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue) {
|
|
|
let legendElem = $(elem).find('svg');
|
|
|
+ let legend = d3.select(legendElem.get(0));
|
|
|
clearLegend(elem);
|
|
|
|
|
|
let legendWidth = Math.floor(legendElem.outerWidth()) - 30;
|
|
|
@@ -115,30 +119,30 @@ function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue
|
|
|
let rangeStep = 10;
|
|
|
let widthFactor = legendWidth / (rangeTo - rangeFrom);
|
|
|
let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
|
|
|
- let legend = d3.select(legendElem.get(0));
|
|
|
- var legendRects = legend.selectAll(".heatmap-opacity-legend-rect").data(valuesRange);
|
|
|
|
|
|
- let legendOpacityScale = getOpacityScale(options, maxValue, minValue);
|
|
|
- legendRects.enter().append("rect")
|
|
|
+ let opacityScale = getOpacityScale(options, maxValue, minValue);
|
|
|
+ legend.selectAll(".heatmap-opacity-legend-rect")
|
|
|
+ .data(valuesRange)
|
|
|
+ .enter().append("rect")
|
|
|
.attr("x", d => d * widthFactor)
|
|
|
.attr("y", 0)
|
|
|
.attr("width", rangeStep * widthFactor)
|
|
|
.attr("height", legendHeight)
|
|
|
.attr("stroke-width", 0)
|
|
|
.attr("fill", options.cardColor)
|
|
|
- .style("opacity", d => legendOpacityScale(d));
|
|
|
+ .style("opacity", d => opacityScale(d));
|
|
|
|
|
|
- drawLegendValues(elem, legendOpacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth);
|
|
|
+ drawLegendValues(elem, opacityScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth);
|
|
|
}
|
|
|
|
|
|
function drawLegendValues(elem, colorScale, rangeFrom, rangeTo, maxValue, minValue, legendWidth) {
|
|
|
- if (legendWidth <= 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
let legendElem = $(elem).find('svg');
|
|
|
let legend = d3.select(legendElem.get(0));
|
|
|
|
|
|
+ if (legendWidth <= 0 || legendElem.get(0).childNodes.length === 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
let legendValueDomain = _.sortBy(colorScale.domain());
|
|
|
let legendValueScale = d3.scaleLinear()
|
|
|
.domain([0, rangeTo])
|
|
|
@@ -185,11 +189,6 @@ function drawSimpleColorLegend(elem, colorScale) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-function clearLegend(elem) {
|
|
|
- let legendElem = $(elem).find('svg');
|
|
|
- legendElem.empty();
|
|
|
-}
|
|
|
-
|
|
|
function drawSimpleOpacityLegend(elem, options) {
|
|
|
let legendElem = $(elem).find('svg');
|
|
|
clearLegend(elem);
|
|
|
@@ -225,6 +224,11 @@ function drawSimpleOpacityLegend(elem, options) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+function clearLegend(elem) {
|
|
|
+ let legendElem = $(elem).find('svg');
|
|
|
+ legendElem.empty();
|
|
|
+}
|
|
|
+
|
|
|
function getColorScale(colorScheme, maxValue, minValue = 0) {
|
|
|
let colorInterpolator = d3[colorScheme.value];
|
|
|
let colorScaleInverted = colorScheme.invert === 'always' ||
|