Skip to content

Commit c4383bc

Browse files
author
Daniel Gröger
committed
Use rect behind text instead of text2 for collision check
1 parent 16adaac commit c4383bc

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

Diff for: src/components/fx/hover.js

+24-7
Original file line numberDiff line numberDiff line change
@@ -1538,6 +1538,9 @@ function hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, commonLabel)
15381538
});
15391539
}
15401540

1541+
var pX = function(x) { return x * fullLayout._invScaleX; };
1542+
var pY = function(y) { return y * fullLayout._invScaleY; };
1543+
15411544
hoverLabels.each(function(d) {
15421545
var ax = d[axKey];
15431546
var crossAx = d[crossAxKey];
@@ -1551,15 +1554,29 @@ function hoverAvoidOverlaps(hoverLabels, rotateLabels, fullLayout, commonLabel)
15511554
var pmax = (axIsX ? fullLayout.width : fullLayout.height);
15521555
// in hovermode avoid overlap between hover labels and axis label
15531556
if(fullLayout.hovermode === 'x' || fullLayout.hovermode === 'y') {
1554-
// extent of rect behind hover label on cross axis (without arrow):
1557+
// extent of rect behind hover label on cross axis:
15551558
var offsets = getHoverLabelOffsets(d, rotateLabels);
1556-
var shiftX = getTextShiftX(d);
1557-
// calculation based on alignHoverText function
1558-
var offsetRectX = (shiftX.text2ShiftX + (shiftX.alignShift - 1) * d.tx2width / 2 + offsets.x) * fullLayout._invScaleX;
1559-
var offsetRectY = (offsets.y - d.by / 2 - 1) * fullLayout._invScaleY;
1559+
var anchor = d.anchor;
1560+
var horzSign = anchor === 'end' ? -1 : 1;
1561+
var labelMin;
1562+
var labelMax;
1563+
if(anchor === 'middle') {
1564+
// use extent of centered rect either on x or y axis depending on current axis
1565+
labelMin = d.crossPos + (axIsX ? pY(offsets.y - d.by / 2) : pX(d.bx / 2 + d.tx2width / 2));
1566+
labelMax = labelMin + (axIsX ? pY(d.by) : pX(d.bx));
1567+
} else {
1568+
// use extend of path (see alignHoverText function) without arrow
1569+
if(axIsX) {
1570+
labelMin = d.crossPos + pY(HOVERARROWSIZE + offsets.y) - pY(d.by / 2 - HOVERARROWSIZE);
1571+
labelMax = labelMin + pY(d.by);
1572+
} else {
1573+
var startX = pX(horzSign * HOVERARROWSIZE + offsets.x);
1574+
var endX = startX + pX(horzSign * d.bx);
1575+
labelMin = d.crossPos + Math.min(startX, endX);
1576+
labelMax = d.crossPos + Math.max(startX, endX);
1577+
}
1578+
}
15601579

1561-
var labelMin = d.crossPos + (axIsX ? offsetRectY : offsetRectX);
1562-
var labelMax = labelMin + (axIsX ? d.tx2width * fullLayout._invScaleX : (d.by + 2) * fullLayout._invScaleY);
15631580
if(axIsX) {
15641581
if(axisLabelMinY !== undefined && axisLabelMaxY !== undefined && Math.min(labelMax, axisLabelMaxY) - Math.max(labelMin, axisLabelMinY) > 1) {
15651582
// has at least 1 pixel overlap with axis label

Diff for: test/jasmine/tests/hover_label_test.js

+33
Original file line numberDiff line numberDiff line change
@@ -1582,6 +1582,39 @@ describe('hover info', function() {
15821582
.then(done, done.fail);
15831583
});
15841584
});
1585+
describe('overlapping hover labels of different lengths', function() {
1586+
var data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20].map(v=>({x:[100,200,300],y:[v,v+1,v+2]}));
1587+
var layout = {
1588+
width: 500, height: 400, showlegend: false,
1589+
margin: {l: 100, r: 100, t: 100, b: 100},
1590+
hovermode: 'x'
1591+
};
1592+
1593+
var gd;
1594+
1595+
beforeEach(function(done) {
1596+
gd = createGraphDiv();
1597+
Plotly.newPlot(gd, data, layout).then(done);
1598+
});
1599+
1600+
function labelCount() {
1601+
return d3Select(gd).selectAll('g.hovertext').size();
1602+
}
1603+
1604+
it('does not show labels that would overlap the axis hover label', function(done) {
1605+
_hoverNatural(gd, 130, 100);
1606+
1607+
expect(labelCount()).toBe(14);
1608+
1609+
Plotly.relayout(gd, {'yaxis.domain': [0.2, 0.8]})
1610+
.then(function() {
1611+
_hoverNatural(gd, 130, 100);
1612+
1613+
expect(labelCount()).toBe(12);
1614+
})
1615+
.then(done, done.fail);
1616+
});
1617+
});
15851618

15861619
describe('alignment while avoiding overlaps:', function() {
15871620
var gd;

0 commit comments

Comments
 (0)