Skip to content

Commit 90c653b

Browse files
committed
adapt Axes.calcTicks output for tickson:'boundaries'
1 parent 3a953db commit 90c653b

File tree

2 files changed

+105
-5
lines changed

2 files changed

+105
-5
lines changed

src/plots/cartesian/axes.js

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,14 +1610,41 @@ axes.drawOne = function(gd, ax, opts) {
16101610
var subplotsWithAx = axes.getSubplots(gd, ax);
16111611

16121612
var vals = ax._vals = axes.calcTicks(ax);
1613-
// We remove zero lines, grid lines, and inside ticks if they're within 1px of the end
1614-
// The key case here is removing zero lines when the axis bound is zero
1615-
var valsClipped = ax._valsClipped = axes.clipEnds(ax, vals);
16161613

16171614
if(!ax.visible) return;
16181615

16191616
var transFn = axes.makeTransFn(ax);
16201617

1618+
// We remove zero lines, grid lines, and inside ticks if they're within 1px of the end
1619+
// The key case here is removing zero lines when the axis bound is zero
1620+
var valsClipped;
1621+
var tickVals;
1622+
var gridVals;
1623+
1624+
if(ax.tickson === 'boundaries') {
1625+
// draw ticks and grid lines 1/2 a 'category' to the left,
1626+
// add one item at axis tail
1627+
var valsBoundaries = vals.map(function(d) {
1628+
var d2 = Lib.extendFlat({}, d);
1629+
d2.x -= 0.5;
1630+
return d2;
1631+
});
1632+
// not used for labels; no need to worry about the other tickTextObj keys
1633+
var d2 = Lib.extendFlat({}, vals[vals.length - 1]);
1634+
d2.x += 0.5;
1635+
valsBoundaries.push(d2);
1636+
1637+
valsClipped = axes.clipEnds(ax, valsBoundaries);
1638+
tickVals = ax.ticks === 'inside' ? valsClipped : valsBoundaries;
1639+
gridVals = valsClipped;
1640+
} else {
1641+
valsClipped = axes.clipEnds(ax, vals);
1642+
tickVals = ax.ticks === 'inside' ? valsClipped : vals;
1643+
gridVals = valsClipped;
1644+
}
1645+
1646+
ax._valsClipped = valsClipped;
1647+
16211648
if(!fullLayout._hasOnlyLargeSploms) {
16221649
// keep track of which subplots (by main conteraxis) we've already
16231650
// drawn grids for, so we don't overdraw overlaying subplots
@@ -1637,7 +1664,7 @@ axes.drawOne = function(gd, ax, opts) {
16371664
'M' + counterAxis._offset + ',0h' + counterAxis._length;
16381665

16391666
axes.drawGrid(gd, ax, {
1640-
vals: valsClipped,
1667+
vals: gridVals,
16411668
layer: plotinfo.gridlayer.select('.' + axId),
16421669
path: gridPath,
16431670
transFn: transFn
@@ -1652,7 +1679,6 @@ axes.drawOne = function(gd, ax, opts) {
16521679
}
16531680

16541681
var tickSigns = axes.getTickSigns(ax);
1655-
var tickVals = ax.ticks === 'inside' ? valsClipped : vals;
16561682
var tickSubplots = [];
16571683

16581684
if(ax.ticks) {

test/jasmine/tests/axes_test.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,6 +3099,80 @@ describe('Test axes', function() {
30993099
.then(done);
31003100
});
31013101
});
3102+
3103+
describe('*tickson*:', function() {
3104+
var gd;
3105+
beforeEach(function() {
3106+
gd = createGraphDiv();
3107+
});
3108+
afterEach(destroyGraphDiv);
3109+
3110+
function getPositions(query) {
3111+
var pos = [];
3112+
d3.selectAll(query).each(function() {
3113+
pos.push(this.getBoundingClientRect().x);
3114+
});
3115+
return pos;
3116+
}
3117+
3118+
function _assert(msg, exp) {
3119+
var ticks = getPositions('path.xtick');
3120+
var gridLines = getPositions('path.xgrid');
3121+
var tickLabels = getPositions('.xtick > text');
3122+
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+
}
3130+
3131+
it('should respond to relayout', function(done) {
3132+
Plotly.plot(gd, [{
3133+
x: ['a', 'b', 'c'],
3134+
y: [1, 2, 1]
3135+
}], {
3136+
xaxis: {
3137+
ticks: 'inside',
3138+
showgrid: true
3139+
}
3140+
})
3141+
.then(function() {
3142+
_assert('on labels (defaults)', {
3143+
ticks: [110.75, 350, 589.25],
3144+
gridLines: [110.75, 350, 589.25],
3145+
tickLabels: [106.421, 345.671, 585.25]
3146+
});
3147+
return Plotly.relayout(gd, 'xaxis.tickson', 'boundaries');
3148+
})
3149+
.then(function() {
3150+
_assert('inside on boundaries', {
3151+
ticks: [230.369, 469.619], // N.B. first and last tick are clipped
3152+
gridLines: [230.369, 469.619],
3153+
tickLabels: [106.421875, 345.671875, 585.25]
3154+
});
3155+
return Plotly.relayout(gd, 'xaxis.ticks', 'outside');
3156+
})
3157+
.then(function() {
3158+
_assert('outside on boundaries', {
3159+
ticks: [-8.869, 230.369, 469.619, 708.869],
3160+
gridLines: [230.369, 469.619],
3161+
tickLabels: [106.421875, 345.671875, 585.25]
3162+
});
3163+
return Plotly.restyle(gd, 'x', [[1, 2, 1]]);
3164+
})
3165+
.then(function() {
3166+
_assert('fallback to *labels* on non-category axes', {
3167+
ticks: [110.75, 206.449, 302.149, 397.85, 493.549, 589.25],
3168+
gridLines: [110.75, 206.449, 302.149, 397.85, 493.549, 589.25],
3169+
tickLabels: [106.421, 197.121, 292.821, 388.521, 484.221, 584.921]
3170+
});
3171+
})
3172+
.catch(failTest)
3173+
.then(done);
3174+
});
3175+
});
31023176
});
31033177

31043178
function getZoomInButton(gd) {

0 commit comments

Comments
 (0)