Commit 55b24be1 by Alexander Zobnin

heatmap: refactor, directive for color legend

parent ef9dd014
///<reference path="../../../headers/common.d.ts" />
import angular from 'angular';
import _ from 'lodash';
import $ from 'jquery';
import d3 from 'd3';
import {contextSrv} from 'app/core/core';
let module = angular.module('grafana.directives');
module.directive('colorLegend', function() {
return {
restrict: 'E',
template: '<div class="heatmap-color-legend"><svg width="19em" height="2em"></svg></div>',
link: function(scope, elem, attrs) {
let ctrl = scope.ctrl;
let panel = scope.ctrl.panel;
render();
ctrl.events.on('render', function() {
render();
});
function render() {
let legendElem = $(elem).find('svg');
let legendWidth = Math.floor(legendElem.outerWidth());
if (panel.color.mode === 'spectrum') {
let colorScheme = _.find(ctrl.colorSchemes, {value: panel.color.colorScheme});
let colorScale = getColorScale(colorScheme, legendWidth);
drawColorLegend(elem, colorScale);
} else if (panel.color.mode === 'opacity') {
let colorOptions = panel.color;
drawOpacityLegend(elem, colorOptions);
}
}
}
};
});
module.directive('heatmapLegend', function() {
return {
restrict: 'E',
template: '<div class="heatmap-color-legend"><svg width="19em" height="2em"></svg></div>',
link: function(scope, elem, attrs) {
let ctrl = scope.ctrl;
let panel = scope.ctrl.panel;
ctrl.events.on('render', function() {
if (!_.isEmpty(ctrl.data)) {
let legendElem = $(elem).find('svg');
let legendWidth = Math.floor(legendElem.outerWidth());
if (panel.color.mode === 'spectrum') {
let colorScheme = _.find(ctrl.colorSchemes, {value: panel.color.colorScheme});
let colorScale = getColorScale(colorScheme, legendWidth);
drawColorLegend(elem, colorScale);
} else if (panel.color.mode === 'opacity') {
let colorOptions = panel.color;
drawOpacityLegend(elem, colorOptions);
}
}
});
}
};
});
function drawColorLegend(elem, colorScale) {
let legendElem = $(elem).find('svg');
legendElem.find("rect").remove();
let legendWidth = Math.floor(legendElem.outerWidth());
let legendHeight = legendElem.attr("height");
let rangeStep = 2;
let valuesRange = d3.range(0, legendWidth, rangeStep);
let legend = d3.select(legendElem.get(0));
var legendRects = legend.selectAll(".heatmap-color-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", d => colorScale(d));
}
function clearLegend(elem) {
let legendElem = $(elem).find('svg');
legendElem.find("rect").remove();
}
function drawOpacityLegend(elem, options) {
let legendElem = $(elem).find('svg');
clearLegend(elem);
let legend = d3.select(legendElem.get(0));
let legendWidth = Math.floor(legendElem.outerWidth());
let legendHeight = legendElem.attr("height");
let legendOpacityScale;
if (options.colorScale === 'linear') {
legendOpacityScale = d3.scaleLinear()
.domain([0, legendWidth])
.range([0, 1]);
} else if (options.colorScale === 'sqrt') {
legendOpacityScale = d3.scalePow().exponent(options.exponent)
.domain([0, legendWidth])
.range([0, 1]);
}
let rangeStep = 1;
let valuesRange = d3.range(0, legendWidth, rangeStep);
var legendRects = legend.selectAll(".heatmap-opacity-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep)
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", options.cardColor)
.style("opacity", d => legendOpacityScale(d));
}
function getColorScale(colorScheme, maxValue, minValue = 0) {
let colorInterpolator = d3[colorScheme.value];
let colorScaleInverted = colorScheme.invert === 'always' ||
(colorScheme.invert === 'dark' && !contextSrv.user.lightTheme);
let start = colorScaleInverted ? maxValue : minValue;
let end = colorScaleInverted ? minValue : maxValue;
return d3.scaleSequential(colorInterpolator).domain([start, end]);
}
///<reference path="../../../headers/common.d.ts" /> ///<reference path="../../../headers/common.d.ts" />
import _ from 'lodash';
import $ from 'jquery';
import d3 from 'd3';
import {contextSrv} from 'app/core/core';
const COLOR_LEGEND_SELECTOR = '.heatmap-color-legend';
export class HeatmapDisplayEditorCtrl { export class HeatmapDisplayEditorCtrl {
panel: any; panel: any;
......
///<reference path="../../../headers/common.d.ts" /> ///<reference path="../../../headers/common.d.ts" />
import './color_legend';
import {HeatmapCtrl} from './heatmap_ctrl'; import {HeatmapCtrl} from './heatmap_ctrl';
export { export {
......
...@@ -25,9 +25,6 @@ ...@@ -25,9 +25,6 @@
<label class="gf-form-label width-9">Exponent</label> <label class="gf-form-label width-9">Exponent</label>
<input type="number" class="gf-form-input width-8" placeholder="auto" data-placement="right" bs-tooltip="''" ng-model="ctrl.panel.color.exponent" ng-change="ctrl.refresh()" ng-model-onblur> <input type="number" class="gf-form-input width-8" placeholder="auto" data-placement="right" bs-tooltip="''" ng-model="ctrl.panel.color.exponent" ng-change="ctrl.refresh()" ng-model-onblur>
</div> </div>
<div class="gf-form">
<svg id="heatmap-opacity-legend" width="19em" height="2em"></svg>
</div>
</div> </div>
<div ng-show="ctrl.panel.color.mode === 'spectrum'"> <div ng-show="ctrl.panel.color.mode === 'spectrum'">
...@@ -37,9 +34,10 @@ ...@@ -37,9 +34,10 @@
<select class="input-small gf-form-input" ng-model="ctrl.panel.color.colorScheme" ng-options="s.value as s.name for s in ctrl.colorSchemes" ng-change="ctrl.render()"></select> <select class="input-small gf-form-input" ng-model="ctrl.panel.color.colorScheme" ng-options="s.value as s.name for s in ctrl.colorSchemes" ng-change="ctrl.render()"></select>
</div> </div>
</div> </div>
<div class="gf-form"> </div>
<svg id="heatmap-color-legend" width="19em" height="2em"></svg>
</div> <div class="gf-form">
<color-legend></color-legend>
</div> </div>
</div> </div>
......
...@@ -706,78 +706,11 @@ export default function link(scope, elem, attrs, ctrl) { ...@@ -706,78 +706,11 @@ export default function link(scope, elem, attrs, ctrl) {
} }
} }
function drawColorLegend() {
d3.select("#heatmap-color-legend").selectAll("rect").remove();
let legend = d3.select("#heatmap-color-legend");
let legendWidth = Math.floor($(d3.select("#heatmap-color-legend").node()).outerWidth());
let legendHeight = d3.select("#heatmap-color-legend").attr("height");
let legendColorScale = getColorScale(legendWidth);
let rangeStep = 2;
let valuesRange = d3.range(0, legendWidth, rangeStep);
var legendRects = legend.selectAll(".heatmap-color-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep + 1) // Overlap rectangles to prevent gaps
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", d => {
return legendColorScale(d);
});
}
function drawOpacityLegend() {
d3.select("#heatmap-opacity-legend").selectAll("rect").remove();
let legend = d3.select("#heatmap-opacity-legend");
let legendWidth = Math.floor($(d3.select("#heatmap-opacity-legend").node()).outerWidth());
let legendHeight = d3.select("#heatmap-opacity-legend").attr("height");
let legendOpacityScale;
if (panel.color.colorScale === 'linear') {
legendOpacityScale = d3.scaleLinear()
.domain([0, legendWidth])
.range([0, 1]);
} else if (panel.color.colorScale === 'sqrt') {
legendOpacityScale = d3.scalePow().exponent(panel.color.exponent)
.domain([0, legendWidth])
.range([0, 1]);
}
let rangeStep = 1;
let valuesRange = d3.range(0, legendWidth, rangeStep);
var legendRects = legend.selectAll(".heatmap-opacity-legend-rect").data(valuesRange);
legendRects.enter().append("rect")
.attr("x", d => d)
.attr("y", 0)
.attr("width", rangeStep)
.attr("height", legendHeight)
.attr("stroke-width", 0)
.attr("fill", panel.color.cardColor)
.style("opacity", d => {
return legendOpacityScale(d);
});
}
function render() { function render() {
data = ctrl.data; data = ctrl.data;
panel = ctrl.panel; panel = ctrl.panel;
timeRange = ctrl.range; timeRange = ctrl.range;
// Draw only if color editor is opened
if (!d3.select("#heatmap-color-legend").empty()) {
drawColorLegend();
}
if (!d3.select("#heatmap-opacity-legend").empty()) {
drawOpacityLegend();
}
if (!setElementHeight() || !data) { if (!setElementHeight() || !data) {
return; return;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment