Skip to content
1 change: 1 addition & 0 deletions draftlogs/7872_fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Prevent outside bar text for zero-length bars from overlapping axis tick labels [[#7872](https://github.com/plotly/plotly.js/pull/7872)]
46 changes: 42 additions & 4 deletions src/traces/bar/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, r, overhead, op
// get trace attributes
var trace = cd[0].trace;
var isHorizontal = trace.orientation === 'h';
var zeroBarDir = getZeroBarDir(cd, isHorizontal, xa, ya);

var text = getText(fullLayout, cd, i, xa, ya);

Expand Down Expand Up @@ -707,7 +708,7 @@ function appendBarText(gd, plotinfo, bar, cd, i, x0, x1, y0, y1, r, overhead, op
transform = toMoveOutsideBar(x0, x1, y0, y1, textBB, {
isHorizontal: isHorizontal,
constrained: constrained,
angle: angle
zeroBarDir: zeroBarDir

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
zeroBarDir: zeroBarDir
angle: angle,
zeroBarDir: zeroBarDir

angle should be added back in here. My fault, I mistakenly suggested deleting it.

});
} else {
constrained = trace.constraintext === 'both' || trace.constraintext === 'inside';
Expand Down Expand Up @@ -957,12 +958,17 @@ function toMoveOutsideBar(x0, x1, y0, y1, textBB, opts) {
var anchorX = 0;
var anchorY = 0;

var dir = isHorizontal ? dirSign(x1, x0) : dirSign(y0, y1);
var dir;
if ((isHorizontal ? x0 === x1 : y0 === y1) && opts.zeroBarDir) {
dir = opts.zeroBarDir;
} else {
dir = isHorizontal ? dirSign(x1, x0) : dirSign(y0, y1);
}
if (isHorizontal) {
targetX = x1 - dir * textpad;
targetX = x1 - dir * (textpad + axisPad);
anchorX = dir * extrapad;
} else {
targetY = y1 + dir * textpad;
targetY = y1 + dir * (textpad + axisPad);
Comment thread
vizansh marked this conversation as resolved.
Comment on lines +968 to +971

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
targetX = x1 - dir * (textpad + axisPad);
anchorX = dir * extrapad;
} else {
targetY = y1 + dir * textpad;
targetY = y1 + dir * (textpad + axisPad);
targetX = x1 - dir * textpad;
anchorX = dir * extrapad;
} else {
targetY = y1 + dir * textpad;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vizansh I've added a new comment with the suggestion, could you apply it? The reference to axisPad should be removed.

anchorY = -dir * extrapad;
}

Expand Down Expand Up @@ -999,6 +1005,38 @@ function getTextPosition(trace, index) {
return helpers.coerceEnumerated(attributeTextPosition, value);
}

function getZeroBarDir(cd, isHorizontal, xa, ya) {
var hasPositive = false;
var hasNegative = false;

for (var i = 0; i < cd.length; i++) {
var s = cd[i].s;

if (s > 0) {
hasPositive = true;
} else if (s < 0) {
hasNegative = true;
}

if (hasPositive && hasNegative) {
return 0;
}
}

var axis = isHorizontal ? xa : ya;
var positiveDir = -dirSign(axis.range[0], axis.range[1]);

if (!hasNegative) {
return positiveDir;
}

if (!hasPositive) {
return -positiveDir;
}

return 0;
}

function calcTexttemplate(fullLayout, cd, index, xa, ya) {
var trace = cd[0].trace;
var texttemplate = Lib.castOption(trace, index, 'texttemplate');
Expand Down
28 changes: 28 additions & 0 deletions test/jasmine/tests/bar_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,34 @@ describe('A bar plot', function() {
.then(done, done.fail);
});

it('should keep zero-value outside labels on the same side as negative bars', function(done) {
Comment thread
vizansh marked this conversation as resolved.
var data = [{
y: [-10, 0, -30],
type: 'bar',
text: ['a', 'zero', 'c'],
textposition: 'outside'
}];

Plotly.newPlot(gd, data).then(function() {
var traceNodes = getAllTraceNodes(gd);
var barNodes = getAllBarNodes(traceNodes[0]);
var foundTextNodes;

for(var i = 0; i < barNodes.length; i++) {
var barNode = barNodes[i];
var pathNode = barNode.querySelector('path');
var textNode = barNode.querySelector('text');
if(textNode) {
foundTextNodes = true;
assertTextIsBelowPath(textNode, pathNode);
}
}

expect(foundTextNodes).toBe(true);
})
.then(done, done.fail);
});

it('should show bar texts (horizontal case)', function(done) {
var data = [{
x: [10, -20, 30],
Expand Down
Loading