fix: plugin hangs on big values in opacity mode

- legend step is a constant now: 2 pixels
- do not calculate legend if 'No legend'
- remove unnecessary calculations in drawSimple*
This commit is contained in:
Ivan Mikheykin
2019-02-26 09:36:48 +03:00
parent 089f42d940
commit 0537671450
3 changed files with 82 additions and 75 deletions
+41 -39
View File
@@ -3,7 +3,7 @@
System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic/index', 'app/core/core', 'app/core/utils/ticks'], function (_export, _context) { System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic/index', 'app/core/core', 'app/core/utils/ticks'], function (_export, _context) {
"use strict"; "use strict";
var angular, _, $, d3, d3ScaleChromatic, contextSrv, tickStep, mod, MIN_LEGEND_STEPS; var angular, _, $, d3, d3ScaleChromatic, contextSrv, tickStep, mod, LEGEND_STEP_WIDTH;
function drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minValue) { function drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minValue) {
var legendElem = $(elem).find('svg'); var legendElem = $(elem).find('svg');
@@ -13,24 +13,29 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
var legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values var legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values
var legendHeight = legendElem.attr("height"); var legendHeight = legendElem.attr("height");
var rangeStep = 1; var rangeStep = (rangeTo - rangeFrom) / (legendWidth / LEGEND_STEP_WIDTH);
if (rangeTo - rangeFrom > legendWidth) { // width in pixels in legend space of unit segment in range space
rangeStep = Math.floor((rangeTo - rangeFrom) / legendWidth); // rangeStep * witdhFactor == width in pixels of one rangeStep
}
if (rangeStep * MIN_LEGEND_STEPS > rangeTo) {
rangeStep = rangeTo / MIN_LEGEND_STEPS;
}
var widthFactor = legendWidth / (rangeTo - rangeFrom); var widthFactor = legendWidth / (rangeTo - rangeFrom);
var valuesRange = d3.range(rangeFrom, rangeTo, rangeStep); var valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
// console.debug({
// "rangeStep": rangeStep,
// "widthFactor": widthFactor,
// "legendWidth": legendWidth,
// "steps": (rangeTo - rangeFrom)/rangeStep,
// });
// console.debug(valuesRange);
var colorScale = getColorScale(colorScheme, maxValue, minValue); var colorScale = getColorScale(colorScheme, maxValue, minValue);
legend.selectAll(".status-heatmap-color-legend-rect").data(valuesRange).enter().append("rect").attr("x", function (d) { legend.selectAll(".status-heatmap-color-legend-rect").data(valuesRange).enter().append("rect")
// translate from range space into pixels
// and shift all rectangles to the right by 10
.attr("x", function (d) {
return d * widthFactor + 10; return d * widthFactor + 10;
}) // shift all color rectangles to the right }).attr("y", 0)
.attr("y", 0).attr("width", rangeStep * widthFactor + 1) // Overlap rectangles to prevent gaps // rectangles are slightly overlaped to prevent gaps
.attr("height", legendHeight).attr("stroke-width", 0).attr("fill", function (d) { .attr("width", LEGEND_STEP_WIDTH + 1).attr("height", legendHeight).attr("stroke-width", 0).attr("fill", function (d) {
return colorScale(d); return colorScale(d);
}); });
@@ -45,20 +50,21 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
var legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values var legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values
var legendHeight = legendElem.attr("height"); var legendHeight = legendElem.attr("height");
var rangeStep = 10; var rangeStep = (rangeTo - rangeFrom) / (legendWidth / LEGEND_STEP_WIDTH);
// width in pixels in legend space of unit segment in range space
// rangeStep * witdhFactor == width in pixels of one rangeStep
var widthFactor = legendWidth / (rangeTo - rangeFrom); var widthFactor = legendWidth / (rangeTo - rangeFrom);
if (rangeStep * MIN_LEGEND_STEPS > rangeTo) {
rangeStep = rangeTo / MIN_LEGEND_STEPS;
}
var valuesRange = d3.range(rangeFrom, rangeTo, rangeStep); var valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
var opacityScale = getOpacityScale(options, maxValue, minValue); var opacityScale = getOpacityScale(options, maxValue, minValue);
legend.selectAll(".status-heatmap-opacity-legend-rect").data(valuesRange).enter().append("rect").attr("x", function (d) { legend.selectAll(".status-heatmap-opacity-legend-rect").data(valuesRange).enter().append("rect")
// translate from range space into pixels
// and shift all rectangles to the right by 10
.attr("x", function (d) {
return d * widthFactor + 10; return d * widthFactor + 10;
}) // shift all opacity rectangles to the right }).attr("y", 0)
.attr("y", 0).attr("width", rangeStep * widthFactor).attr("height", legendHeight).attr("stroke-width", 0).attr("fill", options.cardColor).style("opacity", function (d) { // rectangles are slightly overlaped to prevent gaps
.attr("width", LEGEND_STEP_WIDTH + 1).attr("height", legendHeight).attr("stroke-width", 0).attr("fill", options.cardColor).style("opacity", function (d) {
return opacityScale(d); return opacityScale(d);
}); });
@@ -180,22 +186,18 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
function drawSimpleColorLegend(elem, colorScale) { function drawSimpleColorLegend(elem, colorScale) {
var legendElem = $(elem).find('svg'); var legendElem = $(elem).find('svg');
var legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
var legendWidth = Math.floor(legendElem.outerWidth()); var legendWidth = Math.floor(legendElem.outerWidth());
var legendHeight = legendElem.attr("height"); var legendHeight = legendElem.attr("height");
if (legendWidth) { if (legendWidth) {
var valuesNumber = Math.floor(legendWidth / 2); var valuesRange = d3.range(0, legendWidth, LEGEND_STEP_WIDTH);
var rangeStep = Math.floor(legendWidth / valuesNumber);
var valuesRange = d3.range(0, legendWidth, rangeStep);
var legend = d3.select(legendElem.get(0)); legend.selectAll(".status-heatmap-color-legend-rect").data(valuesRange).enter().append("rect").attr("x", function (d) {
var legendRects = legend.selectAll(".status-heatmap-color-legend-rect").data(valuesRange);
legendRects.enter().append("rect").attr("x", function (d) {
return d; return d;
}).attr("y", 0).attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps }).attr("y", 0).attr("width", LEGEND_STEP_WIDTH + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight).attr("stroke-width", 0).attr("fill", function (d) { .attr("height", legendHeight).attr("stroke-width", 0).attr("fill", function (d) {
return colorScale(d); return colorScale(d);
}); });
@@ -204,10 +206,9 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
function drawSimpleOpacityLegend(elem, options) { function drawSimpleOpacityLegend(elem, options) {
var legendElem = $(elem).find('svg'); var legendElem = $(elem).find('svg');
var graphElem = $(elem); var legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
var legend = d3.select(legendElem.get(0));
var legendWidth = Math.floor(legendElem.outerWidth()); var legendWidth = Math.floor(legendElem.outerWidth());
var legendHeight = legendElem.attr("height"); var legendHeight = legendElem.attr("height");
@@ -219,13 +220,11 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
legendOpacityScale = d3.scalePow().exponent(options.exponent).domain([0, legendWidth]).range([0, 1]); legendOpacityScale = d3.scalePow().exponent(options.exponent).domain([0, legendWidth]).range([0, 1]);
} }
var rangeStep = 10; var valuesRange = d3.range(0, legendWidth, LEGEND_STEP_WIDTH);
var valuesRange = d3.range(0, legendWidth, rangeStep);
var legendRects = legend.selectAll(".status-heatmap-opacity-legend-rect").data(valuesRange);
legendRects.enter().append("rect").attr("x", function (d) { legend.selectAll(".status-heatmap-opacity-legend-rect").data(valuesRange).enter().append("rect").attr("x", function (d) {
return d; return d;
}).attr("y", 0).attr("width", rangeStep).attr("height", legendHeight).attr("stroke-width", 0).attr("fill", options.cardColor).style("opacity", function (d) { }).attr("y", 0).attr("width", LEGEND_STEP_WIDTH + 1).attr("height", legendHeight).attr("stroke-width", 0).attr("fill", options.cardColor).style("opacity", function (d) {
return legendOpacityScale(d); return legendOpacityScale(d);
}); });
} }
@@ -331,7 +330,7 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
}], }],
execute: function () { execute: function () {
mod = angular.module('grafana.directives'); mod = angular.module('grafana.directives');
MIN_LEGEND_STEPS = 10; LEGEND_STEP_WIDTH = 2;
/** /**
@@ -386,6 +385,9 @@ System.register(['angular', 'lodash', 'jquery', 'd3', './libs/d3-scale-chromatic
function render() { function render() {
clearLegend(elem); clearLegend(elem);
if (!ctrl.panel.legend.show) {
return;
}
if (!_.isEmpty(ctrl.cardsData) && !_.isEmpty(ctrl.cardsData.cards)) { if (!_.isEmpty(ctrl.cardsData) && !_.isEmpty(ctrl.cardsData.cards)) {
var rangeFrom = ctrl.cardsData.minValue; var rangeFrom = ctrl.cardsData.minValue;
var rangeTo = ctrl.cardsData.maxValue; var rangeTo = ctrl.cardsData.maxValue;
+1 -1
View File
File diff suppressed because one or more lines are too long
+40 -35
View File
@@ -8,7 +8,7 @@ import {tickStep} from 'app/core/utils/ticks';
let mod = angular.module('grafana.directives'); let mod = angular.module('grafana.directives');
const MIN_LEGEND_STEPS = 10; const LEGEND_STEP_WIDTH = 2;
/** /**
* Color legend for heatmap editor. * Color legend for heatmap editor.
@@ -62,6 +62,9 @@ mod.directive('statusHeatmapLegend', function() {
function render() { function render() {
clearLegend(elem); clearLegend(elem);
if (!ctrl.panel.legend.show) {
return
}
if (!_.isEmpty(ctrl.cardsData) && !_.isEmpty(ctrl.cardsData.cards)) { if (!_.isEmpty(ctrl.cardsData) && !_.isEmpty(ctrl.cardsData.cards)) {
let rangeFrom = ctrl.cardsData.minValue; let rangeFrom = ctrl.cardsData.minValue;
let rangeTo = ctrl.cardsData.maxValue; let rangeTo = ctrl.cardsData.maxValue;
@@ -92,25 +95,30 @@ function drawColorLegend(elem, colorScheme, rangeFrom, rangeTo, maxValue, minVal
let legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values let legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values
let legendHeight = legendElem.attr("height"); let legendHeight = legendElem.attr("height");
let rangeStep = 1; let rangeStep = (rangeTo - rangeFrom) / (legendWidth/LEGEND_STEP_WIDTH);
if (rangeTo - rangeFrom > legendWidth) { // width in pixels in legend space of unit segment in range space
rangeStep = Math.floor((rangeTo - rangeFrom) / legendWidth); // rangeStep * witdhFactor == width in pixels of one rangeStep
}
if (rangeStep * MIN_LEGEND_STEPS > rangeTo) {
rangeStep = rangeTo / MIN_LEGEND_STEPS;
}
let widthFactor = legendWidth / (rangeTo - rangeFrom); let widthFactor = legendWidth / (rangeTo - rangeFrom);
let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep); let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
// console.debug({
// "rangeStep": rangeStep,
// "widthFactor": widthFactor,
// "legendWidth": legendWidth,
// "steps": (rangeTo - rangeFrom)/rangeStep,
// });
// console.debug(valuesRange);
let colorScale = getColorScale(colorScheme, maxValue, minValue); let colorScale = getColorScale(colorScheme, maxValue, minValue);
legend.selectAll(".status-heatmap-color-legend-rect") legend.selectAll(".status-heatmap-color-legend-rect")
.data(valuesRange) .data(valuesRange)
.enter().append("rect") .enter().append("rect")
.attr("x", d => d * widthFactor + 10) // shift all color rectangles to the right // translate from range space into pixels
// and shift all rectangles to the right by 10
.attr("x", d => d * widthFactor+10)
.attr("y", 0) .attr("y", 0)
.attr("width", rangeStep * widthFactor + 1) // Overlap rectangles to prevent gaps // rectangles are slightly overlaped to prevent gaps
.attr("width", LEGEND_STEP_WIDTH+1)
.attr("height", legendHeight) .attr("height", legendHeight)
.attr("stroke-width", 0) .attr("stroke-width", 0)
.attr("fill", d => colorScale(d)); .attr("fill", d => colorScale(d));
@@ -126,22 +134,22 @@ function drawOpacityLegend(elem, options, rangeFrom, rangeTo, maxValue, minValue
let legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values let legendWidth = Math.floor(legendElem.outerWidth()) - 30; // narrow legendWidth by 30px to get space for first and last tick values
let legendHeight = legendElem.attr("height"); let legendHeight = legendElem.attr("height");
let rangeStep = 10; let rangeStep = (rangeTo - rangeFrom) / (legendWidth/LEGEND_STEP_WIDTH);
// width in pixels in legend space of unit segment in range space
// rangeStep * witdhFactor == width in pixels of one rangeStep
let widthFactor = legendWidth / (rangeTo - rangeFrom); let widthFactor = legendWidth / (rangeTo - rangeFrom);
if (rangeStep * MIN_LEGEND_STEPS > rangeTo) {
rangeStep = rangeTo / MIN_LEGEND_STEPS;
}
let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep); let valuesRange = d3.range(rangeFrom, rangeTo, rangeStep);
let opacityScale = getOpacityScale(options, maxValue, minValue); let opacityScale = getOpacityScale(options, maxValue, minValue);
legend.selectAll(".status-heatmap-opacity-legend-rect") legend.selectAll(".status-heatmap-opacity-legend-rect")
.data(valuesRange) .data(valuesRange)
.enter().append("rect") .enter().append("rect")
.attr("x", d => d * widthFactor + 10) // shift all opacity rectangles to the right // translate from range space into pixels
// and shift all rectangles to the right by 10
.attr("x", d => d * widthFactor+10)
.attr("y", 0) .attr("y", 0)
.attr("width", rangeStep * widthFactor) // rectangles are slightly overlaped to prevent gaps
.attr("width", LEGEND_STEP_WIDTH+1)
.attr("height", legendHeight) .attr("height", legendHeight)
.attr("stroke-width", 0) .attr("stroke-width", 0)
.attr("fill", options.cardColor) .attr("fill", options.cardColor)
@@ -289,23 +297,21 @@ function drawDiscreteLegendValues(elem, colorOptions, legendWidth) {
function drawSimpleColorLegend(elem, colorScale) { function drawSimpleColorLegend(elem, colorScale) {
let legendElem = $(elem).find('svg'); let legendElem = $(elem).find('svg');
let legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
let legendWidth = Math.floor(legendElem.outerWidth()); let legendWidth = Math.floor(legendElem.outerWidth());
let legendHeight = legendElem.attr("height"); let legendHeight = legendElem.attr("height");
if (legendWidth) { if (legendWidth) {
let valuesNumber = Math.floor(legendWidth / 2); let valuesRange = d3.range(0, legendWidth, LEGEND_STEP_WIDTH);
let rangeStep = Math.floor(legendWidth / valuesNumber);
let valuesRange = d3.range(0, legendWidth, rangeStep);
let legend = d3.select(legendElem.get(0)); legend.selectAll(".status-heatmap-color-legend-rect")
var legendRects = legend.selectAll(".status-heatmap-color-legend-rect").data(valuesRange); .data(valuesRange)
.enter().append("rect")
legendRects.enter().append("rect")
.attr("x", d => d) .attr("x", d => d)
.attr("y", 0) .attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps .attr("width", LEGEND_STEP_WIDTH + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight) .attr("height", legendHeight)
.attr("stroke-width", 0) .attr("stroke-width", 0)
.attr("fill", d => colorScale(d)); .attr("fill", d => colorScale(d));
@@ -314,10 +320,9 @@ function drawSimpleColorLegend(elem, colorScale) {
function drawSimpleOpacityLegend(elem, options) { function drawSimpleOpacityLegend(elem, options) {
let legendElem = $(elem).find('svg'); let legendElem = $(elem).find('svg');
let graphElem = $(elem); let legend = d3.select(legendElem.get(0));
clearLegend(elem); clearLegend(elem);
let legend = d3.select(legendElem.get(0));
let legendWidth = Math.floor(legendElem.outerWidth()); let legendWidth = Math.floor(legendElem.outerWidth());
let legendHeight = legendElem.attr("height"); let legendHeight = legendElem.attr("height");
@@ -333,14 +338,14 @@ function drawSimpleOpacityLegend(elem, options) {
.range([0, 1]); .range([0, 1]);
} }
let rangeStep = 10; let valuesRange = d3.range(0, legendWidth, LEGEND_STEP_WIDTH);
let valuesRange = d3.range(0, legendWidth, rangeStep);
var legendRects = legend.selectAll(".status-heatmap-opacity-legend-rect").data(valuesRange);
legendRects.enter().append("rect") legend.selectAll(".status-heatmap-opacity-legend-rect")
.data(valuesRange)
.enter().append("rect")
.attr("x", d => d) .attr("x", d => d)
.attr("y", 0) .attr("y", 0)
.attr("width", rangeStep) .attr("width", LEGEND_STEP_WIDTH+1)
.attr("height", legendHeight) .attr("height", legendHeight)
.attr("stroke-width", 0) .attr("stroke-width", 0)
.attr("fill", options.cardColor) .attr("fill", options.cardColor)