Skip to content

Commit eeb9055

Browse files
committed
split overlap algo based on tickson + use tickwidth for extra pad
1 parent bae37be commit eeb9055

File tree

2 files changed

+89
-34
lines changed

2 files changed

+89
-34
lines changed

src/plots/cartesian/axes.js

+19-15
Original file line numberDiff line numberDiff line change
@@ -2337,33 +2337,37 @@ axes.drawLabels = function(gd, ax, opts) {
23372337
});
23382338

23392339
var autoangle = 0;
2340-
for(i = 0; i < lbbArray.length - 1; i++) {
2341-
if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1])) {
2342-
// any overlap at all - set 30 degrees
2343-
autoangle = 30;
2344-
break;
2345-
}
2346-
}
23472340

23482341
if(ax.tickson === 'boundaries') {
2342+
var gap = 2;
2343+
if(ax.ticks) gap += ax.tickwidth / 2;
2344+
23492345
for(i = 0; i < lbbArray.length; i++) {
2346+
var xbnd = vals[i].xbnd;
2347+
var lbb = lbbArray[i];
23502348
if(
2351-
(vals[i].xl !== null && (lbbArray[i].left - ax.l2p(vals[i].xbnd[0])) < 2) ||
2352-
(vals[i].xr !== null && (ax.l2p(vals[i].xbnd[1]) - lbbArray[i].right) < 2)
2349+
(xbnd[0] !== null && (lbb.left - ax.l2p(xbnd[0])) < gap) ||
2350+
(xbnd[1] !== null && (ax.l2p(xbnd[1]) - lbb.right) < gap)
23532351
) {
23542352
autoangle = 90;
23552353
break;
23562354
}
23572355
}
2356+
} else {
2357+
var vLen = vals.length;
2358+
var tickSpacing = Math.abs((vals[vLen - 1].x - vals[0].x) * ax._m) / (vLen - 1);
2359+
var fitBetweenTicks = tickSpacing < maxFontSize * 2.5;
2360+
2361+
// any overlap at all - set 30 degrees or 90 degrees
2362+
for(i = 0; i < lbbArray.length - 1; i++) {
2363+
if(Lib.bBoxIntersect(lbbArray[i], lbbArray[i + 1])) {
2364+
autoangle = fitBetweenTicks ? 90 : 30;
2365+
break;
2366+
}
2367+
}
23582368
}
23592369

23602370
if(autoangle) {
2361-
var tickspacing = Math.abs(
2362-
(vals[vals.length - 1].x - vals[0].x) * ax._m
2363-
) / (vals.length - 1);
2364-
if(tickspacing < maxFontSize * 2.5) {
2365-
autoangle = 90;
2366-
}
23672371
positionLabels(tickLabels, autoangle);
23682372
}
23692373
ax._lastangle = autoangle;

test/jasmine/tests/axes_test.js

+70-19
Original file line numberDiff line numberDiff line change
@@ -3102,33 +3102,35 @@ describe('Test axes', function() {
31023102

31033103
describe('*tickson*:', function() {
31043104
var gd;
3105+
31053106
beforeEach(function() {
31063107
gd = createGraphDiv();
31073108
});
3109+
31083110
afterEach(destroyGraphDiv);
31093111

3110-
function getPositions(query) {
3111-
var pos = [];
3112-
d3.selectAll(query).each(function() {
3113-
pos.push(this.getBoundingClientRect().x);
3114-
});
3115-
return pos;
3116-
}
3112+
it('should respond to relayout', function(done) {
3113+
function getPositions(query) {
3114+
var pos = [];
3115+
d3.selectAll(query).each(function() {
3116+
pos.push(this.getBoundingClientRect().x);
3117+
});
3118+
return pos;
3119+
}
31173120

3118-
function _assert(msg, exp) {
3119-
var ticks = getPositions('path.xtick');
3120-
var gridLines = getPositions('path.xgrid');
3121-
var tickLabels = getPositions('.xtick > text');
3121+
function _assert(msg, exp) {
3122+
var ticks = getPositions('path.xtick');
3123+
var gridLines = getPositions('path.xgrid');
3124+
var tickLabels = getPositions('.xtick > text');
31223125

3123-
expect(ticks).toBeCloseToArray(exp.ticks, 1, msg + '- ticks');
3124-
expect(gridLines).toBeCloseToArray(exp.gridLines, 1, msg + '- grid lines');
3125-
expect(tickLabels.length).toBe(exp.tickLabels.length, msg + '- # of tick labels');
3126-
tickLabels.forEach(function(tl, i) {
3127-
expect(tl).toBeWithin(exp.tickLabels[i], 2, msg + '- tick label ' + i);
3128-
});
3129-
}
3126+
expect(ticks).toBeCloseToArray(exp.ticks, 1, msg + '- ticks');
3127+
expect(gridLines).toBeCloseToArray(exp.gridLines, 1, msg + '- grid lines');
3128+
expect(tickLabels.length).toBe(exp.tickLabels.length, msg + '- # of tick labels');
3129+
tickLabels.forEach(function(tl, i) {
3130+
expect(tl).toBeWithin(exp.tickLabels[i], 2, msg + '- tick label ' + i);
3131+
});
3132+
}
31303133

3131-
it('should respond to relayout', function(done) {
31323134
Plotly.plot(gd, [{
31333135
x: ['a', 'b', 'c'],
31343136
y: [1, 2, 1]
@@ -3172,6 +3174,55 @@ describe('Test axes', function() {
31723174
.catch(failTest)
31733175
.then(done);
31743176
});
3177+
3178+
it('should rotate labels to avoid overlaps', function(done) {
3179+
function _assert(msg, exp) {
3180+
var tickLabels = d3.selectAll('.xtick > text');
3181+
3182+
expect(tickLabels.size()).toBe(exp.angle.length, msg + ' - # of tick labels');
3183+
3184+
tickLabels.each(function(_, i) {
3185+
var t = d3.select(this).attr('transform');
3186+
var rotate = (t.split('rotate(')[1] || '').split(')')[0];
3187+
var angle = rotate.split(',')[0];
3188+
expect(Number(angle)).toBe(exp.angle[i], msg + ' - node ' + i);
3189+
});
3190+
}
3191+
3192+
Plotly.plot(gd, [{
3193+
x: ['A very long title', 'short', 'Another very long title'],
3194+
y: [1, 4, 2]
3195+
}], {
3196+
xaxis: {
3197+
domain: [0.22, 0.78],
3198+
tickson: 'boundaries',
3199+
ticks: 'outside'
3200+
},
3201+
width: 500,
3202+
height: 500
3203+
})
3204+
.then(function() {
3205+
_assert('base - rotated', {
3206+
angle: [90, 90, 90]
3207+
});
3208+
3209+
return Plotly.relayout(gd, 'xaxis.range', [-0.5, 1.5]);
3210+
})
3211+
.then(function() {
3212+
_assert('narrower range - unrotated', {
3213+
angle: [0, 0]
3214+
});
3215+
3216+
return Plotly.relayout(gd, 'xaxis.tickwidth', 10);
3217+
})
3218+
.then(function() {
3219+
_assert('narrow range / wide ticks - rotated', {
3220+
angle: [90, 90]
3221+
});
3222+
})
3223+
.catch(failTest)
3224+
.then(done);
3225+
});
31753226
});
31763227
});
31773228

0 commit comments

Comments
 (0)