grafana/public/app/plugins/panel/graph/align_yaxes.ts

155 lines
4.4 KiB
TypeScript
Raw Normal View History

2018-02-22 04:38:32 -06:00
import _ from 'lodash';
/**
* To align two Y axes by Y level
* @param yAxes data [{min: min_y1, min: max_y1}, {min: min_y2, max: max_y2}]
* @param level Y level
2018-02-22 04:38:32 -06:00
*/
export function alignYLevel(yAxes, level) {
if (isNaN(level) || !checkCorrectAxis(yAxes)) {
2018-03-20 05:37:18 -05:00
return;
}
const [yLeft, yRight] = yAxes;
moveLevelToZero(yLeft, yRight, level);
2018-02-22 04:38:32 -06:00
expandStuckValues(yLeft, yRight);
2018-02-22 04:38:32 -06:00
// one of graphs on zero
const zero = yLeft.min === 0 || yRight.min === 0 || yLeft.max === 0 || yRight.max === 0;
2018-02-22 04:38:32 -06:00
const oneSide = checkOneSide(yLeft, yRight);
2018-02-22 04:38:32 -06:00
if (zero && oneSide) {
yLeft.min = yLeft.max > 0 ? 0 : yLeft.min;
yLeft.max = yLeft.max > 0 ? yLeft.max : 0;
yRight.min = yRight.max > 0 ? 0 : yRight.min;
yRight.max = yRight.max > 0 ? yRight.max : 0;
2018-02-22 04:38:32 -06:00
} else {
if (checkOppositeSides(yLeft, yRight)) {
if (yLeft.min >= 0) {
yLeft.min = -yLeft.max;
yRight.max = -yRight.min;
2018-02-22 04:38:32 -06:00
} else {
yLeft.max = -yLeft.min;
yRight.min = -yRight.max;
2018-02-22 04:38:32 -06:00
}
} else {
const rate = getRate(yLeft, yRight);
2018-02-22 04:38:32 -06:00
if (oneSide) {
// all graphs above the Y level
if (yLeft.min > 0) {
yLeft.min = yLeft.max / rate;
yRight.min = yRight.max / rate;
2018-02-22 04:38:32 -06:00
} else {
yLeft.max = yLeft.min / rate;
yRight.max = yRight.min / rate;
2018-02-22 04:38:32 -06:00
}
} else {
if (checkTwoCross(yLeft, yRight)) {
yLeft.min = yRight.min ? yRight.min * rate : yLeft.min;
yRight.min = yLeft.min ? yLeft.min / rate : yRight.min;
yLeft.max = yRight.max ? yRight.max * rate : yLeft.max;
yRight.max = yLeft.max ? yLeft.max / rate : yRight.max;
2018-02-22 04:38:32 -06:00
} else {
yLeft.min = yLeft.min > 0 ? yRight.min * rate : yLeft.min;
yRight.min = yRight.min > 0 ? yLeft.min / rate : yRight.min;
yLeft.max = yLeft.max < 0 ? yRight.max * rate : yLeft.max;
yRight.max = yRight.max < 0 ? yLeft.max / rate : yRight.max;
2018-02-22 04:38:32 -06:00
}
}
}
}
restoreLevelFromZero(yLeft, yRight, level);
2018-03-12 00:54:03 -05:00
}
function expandStuckValues(yLeft, yRight) {
2018-03-12 00:54:03 -05:00
// wide Y min and max using increased wideFactor
const wideFactor = 0.25;
if (yLeft.max === yLeft.min) {
yLeft.min -= wideFactor;
yLeft.max += wideFactor;
2018-03-12 00:54:03 -05:00
}
if (yRight.max === yRight.min) {
yRight.min -= wideFactor;
yRight.max += wideFactor;
2018-03-12 00:54:03 -05:00
}
}
function moveLevelToZero(yLeft, yRight, level) {
if (level !== 0) {
yLeft.min -= level;
yLeft.max -= level;
yRight.min -= level;
yRight.max -= level;
2018-03-12 00:54:03 -05:00
}
}
function restoreLevelFromZero(yLeft, yRight, level) {
if (level !== 0) {
yLeft.min += level;
yLeft.max += level;
yRight.min += level;
yRight.max += level;
2018-03-12 00:54:03 -05:00
}
}
2018-03-20 05:37:18 -05:00
function checkCorrectAxis(axis) {
return axis.length === 2 && checkCorrectAxes(axis[0]) && checkCorrectAxes(axis[1]);
}
function checkCorrectAxes(axes) {
return 'min' in axes && 'max' in axes;
}
function checkOneSide(yLeft, yRight) {
2018-03-12 00:54:03 -05:00
// on the one hand with respect to zero
return (yLeft.min >= 0 && yRight.min >= 0) || (yLeft.max <= 0 && yRight.max <= 0);
2018-03-12 00:54:03 -05:00
}
function checkTwoCross(yLeft, yRight) {
2018-03-12 00:54:03 -05:00
// both across zero
return yLeft.min <= 0 && yLeft.max >= 0 && yRight.min <= 0 && yRight.max >= 0;
2018-03-12 00:54:03 -05:00
}
function checkOppositeSides(yLeft, yRight) {
// on the opposite sides with respect to zero
return (yLeft.min >= 0 && yRight.max <= 0) || (yLeft.max <= 0 && yRight.min >= 0);
}
function getRate(yLeft, yRight) {
let rateLeft, rateRight, rate;
if (checkTwoCross(yLeft, yRight)) {
rateLeft = yRight.min ? yLeft.min / yRight.min : 0;
rateRight = yRight.max ? yLeft.max / yRight.max : 0;
2018-03-12 00:54:03 -05:00
} else {
if (checkOneSide(yLeft, yRight)) {
const absLeftMin = Math.abs(yLeft.min);
const absLeftMax = Math.abs(yLeft.max);
const absRightMin = Math.abs(yRight.min);
const absRightMax = Math.abs(yRight.max);
const upLeft = _.max([absLeftMin, absLeftMax]);
const downLeft = _.min([absLeftMin, absLeftMax]);
const upRight = _.max([absRightMin, absRightMax]);
const downRight = _.min([absRightMin, absRightMax]);
2018-03-12 00:54:03 -05:00
rateLeft = downLeft ? upLeft / downLeft : upLeft;
rateRight = downRight ? upRight / downRight : upRight;
} else {
if (yLeft.min > 0 || yRight.min > 0) {
rateLeft = yLeft.max / yRight.max;
2018-03-12 00:54:03 -05:00
rateRight = 0;
} else {
rateLeft = 0;
rateRight = yLeft.min / yRight.min;
2018-03-12 00:54:03 -05:00
}
}
2018-02-22 04:38:32 -06:00
}
2018-03-12 00:54:03 -05:00
rate = rateLeft > rateRight ? rateLeft : rateRight;
return rate;
2018-02-22 04:38:32 -06:00
}