|
|
|
|
@ -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; |
|
|
|
|
} |
|
|
|
|
|