Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 86f710c

Browse files
committed
2nd look at mutlicategory positioning
- compute and use tick-label height to position secondary labels - disallow 30deg tick label rotation when fixing overlaps - use ax._boundingBox to position axis title on multicategory axes.
1 parent 0f0661e commit 86f710c

File tree

1 file changed

+58
-40
lines changed

1 file changed

+58
-40
lines changed

src/plots/cartesian/axes.js

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,23 +1745,25 @@ axes.drawOne = function(gd, ax, opts) {
17451745

17461746
// tick labels - for now just the main labels.
17471747
// TODO: mirror labels, esp for subplots
1748-
var labelFns = axes.makeLabelFns(ax, mainLinePosition);
17491748

1750-
seq.push(function() {
1751-
return axes.drawLabels(gd, ax, {
1752-
vals: vals,
1753-
layer: mainAxLayer,
1754-
transFn: transFn,
1755-
labelXFn: labelFns.labelXFn,
1756-
labelYFn: labelFns.labelYFn,
1757-
labelAnchorFn: labelFns.labelAnchorFn,
1758-
});
1749+
seq.push(function() {
1750+
var labelFns = axes.makeLabelFns(ax, mainLinePosition);
1751+
return axes.drawLabels(gd, ax, {
1752+
vals: vals,
1753+
layer: mainAxLayer,
1754+
transFn: transFn,
1755+
labelXFn: labelFns.labelXFn,
1756+
labelYFn: labelFns.labelYFn,
1757+
labelAnchorFn: labelFns.labelAnchorFn,
17591758
});
1759+
});
17601760

1761-
if(ax.type === 'multicategory') {
1761+
if(ax.type === 'multicategory') {
1762+
seq.push(function() {
1763+
// TODO?
17621764
// drawDividers()
17631765

1764-
// TODO move to formatMultiCategory
1766+
var secondaryLabelVals = [];
17651767
var lookup = {};
17661768
for(i = 0; i < vals.length; i++) {
17671769
var d = vals[i];
@@ -1771,31 +1773,41 @@ axes.drawOne = function(gd, ax, opts) {
17711773
lookup[d.text2] = [d.x];
17721774
}
17731775
}
1774-
var secondaryLabelVals = [];
17751776
for(var k in lookup) {
17761777
secondaryLabelVals.push(tickTextObj(ax, Lib.interp(lookup[k], 0.5), k));
17771778
}
17781779

1779-
// TODO could do better!
1780-
var secondarayPosition = ax._mainLinePosition + {bottom: 20, top: -20}[ax.side];
1781-
var secondaryLabelFns = axes.makeLabelFns(ax, secondarayPosition);
1780+
var labelHeight = 0;
1781+
ax._selections[ax._id + 'tick'].each(function() {
1782+
var thisLabel = selectTickLabel(this);
17821783

1783-
seq.push(function() {
1784-
return axes.drawLabels(gd, ax, {
1785-
vals: secondaryLabelVals,
1786-
layer: mainAxLayer,
1787-
cls: ax._id + 'tick2',
1788-
transFn: transFn,
1789-
labelXFn: secondaryLabelFns.labelXFn,
1790-
labelYFn: secondaryLabelFns.labelYFn,
1791-
labelAnchorFn: secondaryLabelFns.labelAnchorFn,
1792-
});
1784+
// TODO Drawing.bBox doesn't work when labels are rotated
1785+
// var bb = Drawing.bBox(thisLabel.node());
1786+
var bb = thisLabel.node().getBoundingClientRect();
1787+
labelHeight = Math.max(labelHeight, bb.height);
17931788
});
1794-
}
17951789

1796-
// TODO update 'avoid selection' for multicategory
1797-
seq.push(function() {
1798-
return axes.drawTitle(gd, ax);
1790+
var secondarayPosition;
1791+
if(ax.side === 'bottom') {
1792+
secondarayPosition = mainLinePosition + labelHeight + 2;
1793+
} else {
1794+
secondarayPosition = mainLinePosition - labelHeight - 2;
1795+
if(ax.tickfont) {
1796+
secondarayPosition -= (ax.tickfont.size * LINE_SPACING);
1797+
}
1798+
}
1799+
1800+
var secondaryLabelFns = axes.makeLabelFns(ax, secondarayPosition);
1801+
1802+
return axes.drawLabels(gd, ax, {
1803+
vals: secondaryLabelVals,
1804+
layer: mainAxLayer,
1805+
cls: ax._id + 'tick2',
1806+
transFn: transFn,
1807+
labelXFn: secondaryLabelFns.labelXFn,
1808+
labelYFn: secondaryLabelFns.labelYFn,
1809+
labelAnchorFn: secondaryLabelFns.labelAnchorFn,
1810+
});
17991811
});
18001812
}
18011813

@@ -2360,13 +2372,10 @@ axes.drawLabels = function(gd, ax, opts) {
23602372
var i;
23612373

23622374
tickLabels.each(function(d) {
2363-
var s = d3.select(this);
2364-
var thisLabel = s.select('.text-math-group');
2365-
if(thisLabel.empty()) thisLabel = s.select('text');
2366-
23672375
maxFontSize = Math.max(maxFontSize, d.fontSize);
23682376

23692377
var x = ax.l2p(d.x);
2378+
var thisLabel = selectTickLabel(this);
23702379
var bb = Drawing.bBox(thisLabel.node());
23712380

23722381
lbbArray.push({
@@ -2401,12 +2410,12 @@ axes.drawLabels = function(gd, ax, opts) {
24012410
} else {
24022411
var vLen = vals.length;
24032412
var tickSpacing = Math.abs((vals[vLen - 1].x - vals[0].x) * ax._m) / (vLen - 1);
2404-
var fitBetweenTicks = tickSpacing < maxFontSize * 2.5;
2413+
var rotate90 = (tickSpacing < maxFontSize * 2.5) || ax.type === 'multicategory';
24052414

24062415
// any overlap at all - set 30 degrees or 90 degrees
24072416
for(i = 0; i < lbbArray.length - 1; i++) {
24082417
if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1])) {
2409-
autoangle = fitBetweenTicks ? 90 : 30;
2418+
autoangle = rotate90 ? 90 : 30;
24102419
break;
24112420
}
24122421
}
@@ -2432,15 +2441,18 @@ function drawTitle(gd, ax) {
24322441
var fullLayout = gd._fullLayout;
24332442
var axId = ax._id;
24342443
var axLetter = axId.charAt(0);
2435-
var offsetBase = 1.5;
24362444
var gs = fullLayout._size;
24372445
var fontSize = ax.title.font.size;
24382446

2439-
var transform, counterAxis, x, y;
2447+
var titleStandoff;
2448+
if(ax.type === 'multicategory') {
2449+
titleStandoff = ax._boundingBox.height;
2450+
} else {
2451+
var offsetBase = 1.5;
2452+
titleStandoff = 10 + fontSize * offsetBase + (ax.linewidth ? ax.linewidth - 1 : 0);
24402453
}
24412454

2442-
var titleStandoff = 10 + fontSize * offsetBase +
2443-
(ax.linewidth ? ax.linewidth - 1 : 0);
2455+
var transform, counterAxis, x, y;
24442456

24452457
if(axLetter === 'x') {
24462458
counterAxis = (ax.anchor === 'free') ?
@@ -2595,6 +2607,12 @@ function hasBarsOrFill(gd, ax) {
25952607
return false;
25962608
}
25972609

2610+
function selectTickLabel(gTick) {
2611+
var s = d3.select(gTick);
2612+
var mj = s.select('.text-math-group');
2613+
return mj.empty() ? s.select('text') : mj;
2614+
}
2615+
25982616
/**
25992617
* Find all margin pushers for 2D axes and reserve them for later use
26002618
* Both label and rangeslider automargin calculations happen later so

0 commit comments

Comments
 (0)