fix(chart): STACKED BARS VALUES did not show correctly when data has negative value

This commit is contained in:
lilyzhou 2022-03-03 13:36:06 +08:00
parent be88cb9ba0
commit 749b760750
1 changed files with 71 additions and 28 deletions

View File

@ -47,9 +47,26 @@ export function getTimeOrNumberFormatter(format) {
: getNumberFormatter(format); : getNumberFormatter(format);
} }
function getRectPosInfo(rectObj, yValue) {
const transformAttr = rectObj.attr('transform');
const xPos = parseFloat(rectObj.attr('x'));
const yPos = parseFloat(rectObj.attr('y'));
const rectWidth = parseFloat(rectObj.attr('width'));
const rectHeight = parseFloat(rectObj.attr('height'));
const isPositive = rectObj.attr('class').includes('positive');
return {
xPos,
yPos,
rectWidth,
rectHeight,
transformAttr,
yValue,
isPositive,
};
}
export function drawBarValues(svg, data, stacked, axisFormat) { export function drawBarValues(svg, data, stacked, axisFormat) {
const format = getNumberFormatter(axisFormat); const format = getNumberFormatter(axisFormat);
const countSeriesDisplayed = data.filter(d => !d.disabled).length;
const totalStackedValues = const totalStackedValues =
stacked && data.length !== 0 stacked && data.length !== 0
? data[0].values.map((bar, iBar) => { ? data[0].values.map((bar, iBar) => {
@ -67,34 +84,60 @@ export function drawBarValues(svg, data, stacked, axisFormat) {
.select('g.nv-barsWrap') .select('g.nv-barsWrap')
.append('g') .append('g')
.attr('class', 'bar-chart-label-group'); .attr('class', 'bar-chart-label-group');
svg const rectPosArr = [];
.selectAll('g.nv-group') if (!stacked) {
.filter((d, i) => !stacked || i === countSeriesDisplayed - 1) svg
.selectAll('rect') .selectAll('g.nv-group')
.each(function each(d, index) { .selectAll('rect')
const rectObj = d3.select(this); .each(function each(d) {
const transformAttr = rectObj.attr('transform'); const rectObj = d3.select(this);
const xPos = parseFloat(rectObj.attr('x')); rectPosArr.push(getRectPosInfo(rectObj, d.y));
const yPos = parseFloat(rectObj.attr('y')); });
const rectWidth = parseFloat(rectObj.attr('width')); } else {
const rectHeight = parseFloat(rectObj.attr('height')); totalStackedValues.forEach((d, index) => {
const textEls = groupLabels svg.selectAll('g.nv-group').each(function each() {
.append('text') d3.select(this)
.text(format(stacked ? totalStackedValues[index] : d.y)) .selectAll('rect')
.attr('transform', transformAttr) .filter((f, i) => i === index)
.attr('class', 'bar-chart-label'); .each(function each() {
const rectObj = d3.select(this);
// fine tune text position const current = rectPosArr[index];
const bbox = textEls.node().getBBox(); const rectInfo = getRectPosInfo(
const labelWidth = bbox.width; rectObj,
const labelHeight = bbox.height; totalStackedValues[index],
textEls.attr('x', xPos + rectWidth / 2 - labelWidth / 2); );
if (rectObj.attr('class').includes('positive')) { if (!current) {
textEls.attr('y', yPos - 5); rectPosArr[index] = rectInfo;
} else { } else if (
textEls.attr('y', yPos + rectHeight + labelHeight); // when totalStackedValue is positive, show the value text on the top of the bar, otherwise on the bottom
} totalStackedValues[index] > 0
? rectInfo.yPos < current.yPos
: rectInfo.yPos > current.yPos
) {
rectPosArr[index] = rectInfo;
}
});
});
}); });
}
rectPosArr.forEach(function each(d) {
const textEls = groupLabels
.append('text')
.text(format(d.yValue))
.attr('transform', d.transformAttr)
.attr('class', 'bar-chart-label');
// fine tune text position
const bbox = textEls.node().getBBox();
const labelWidth = bbox.width;
const labelHeight = bbox.height;
textEls.attr('x', d.xPos + d.rectWidth / 2 - labelWidth / 2);
if (d.yValue >= 0) {
textEls.attr('y', d.yPos - 5);
} else {
textEls.attr('y', d.yPos + d.rectHeight + labelHeight);
}
});
}, ANIMATION_TIME); }, ANIMATION_TIME);
} }