Skip to content

Commit 28c328d

Browse files
committed
increase dtick on axes with breaks ...
... when too many ticks fall into breaks. Update axes_breaks-finance baseline which is now showing ticks (!)
1 parent dcceb76 commit 28c328d

File tree

3 files changed

+85
-29
lines changed

3 files changed

+85
-29
lines changed

src/plots/cartesian/axes.js

+43-29
Original file line numberDiff line numberDiff line change
@@ -574,54 +574,73 @@ axes.calcTicks = function calcTicks(ax) {
574574
if((ax._tmin < startTick) !== axrev) return [];
575575

576576
// return the full set of tick vals
577-
var tickVals = [];
578577
if(ax.type === 'category' || ax.type === 'multicategory') {
579578
endTick = (axrev) ? Math.max(-0.5, endTick) :
580579
Math.min(ax._categories.length - 0.5, endTick);
581580
}
582581

583582
var isDLog = (ax.type === 'log') && !(isNumeric(ax.dtick) || ax.dtick.charAt(0) === 'L');
584583

585-
var xPrevious = null;
586-
var maxTicks = Math.max(1000, ax._length || 0);
587-
for(var x = ax._tmin;
588-
(axrev) ? (x >= endTick) : (x <= endTick);
589-
x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)) {
590-
// prevent infinite loops - no more than one tick per pixel,
591-
// and make sure each value is different from the previous
592-
if(tickVals.length > maxTicks || x === xPrevious) break;
593-
xPrevious = x;
584+
var tickVals;
585+
function generateTicks() {
586+
var xPrevious = null;
587+
var maxTicks = Math.max(1000, ax._length || 0);
588+
tickVals = [];
589+
for(var x = ax._tmin;
590+
(axrev) ? (x >= endTick) : (x <= endTick);
591+
x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)) {
592+
// prevent infinite loops - no more than one tick per pixel,
593+
// and make sure each value is different from the previous
594+
if(tickVals.length > maxTicks || x === xPrevious) break;
595+
xPrevious = x;
596+
597+
var minor = false;
598+
if(isDLog && (x !== (x | 0))) {
599+
minor = true;
600+
}
594601

595-
var minor = false;
596-
if(isDLog && (x !== (x | 0))) {
597-
minor = true;
602+
tickVals.push({
603+
minor: minor,
604+
value: x
605+
});
598606
}
599-
600-
tickVals.push({
601-
minor: minor,
602-
value: x
603-
});
604607
}
605608

606-
// If same angle over a full circle, the last tick vals is a duplicate.
607-
// TODO must do something similar for angular date axes.
608-
if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) {
609-
tickVals.pop();
610-
}
609+
generateTicks();
611610

612611
if(ax.breaks) {
612+
var nTicksBefore = tickVals.length;
613+
613614
// remove ticks falling inside breaks
614615
tickVals = tickVals.filter(function(d) {
615616
return ax.maskBreaks(d.value) !== BADNUM;
616617
});
617618

618-
// TODO what to do with "overlapping" ticks?
619+
// if 'numerous' ticks get placed into breaks,
620+
// increase dtick to generate more ticks,
621+
// so that some hopefully fall between breaks
622+
if(ax.tickmode === 'auto' && tickVals.length < nTicksBefore / 6) {
623+
ax.dtick /= 2;
624+
ax._tmin = axes.tickFirst(ax);
625+
generateTicks();
626+
tickVals = tickVals.filter(function(d) {
627+
return ax.maskBreaks(d.value) !== BADNUM;
628+
});
629+
}
630+
631+
// remove "overlapping" ticks (e.g. on either side of a break)
619632
var tf2 = ax.tickfont ? 1.5 * ax.tickfont.size : 0;
620633
tickVals = tickVals.filter(function(d, i, self) {
621634
return !(i && Math.abs(ax.c2p(d.value) - ax.c2p(self[i - 1].value)) < tf2);
622635
});
623636
}
624637

638+
// If same angle over a full circle, the last tick vals is a duplicate.
639+
// TODO must do something similar for angular date axes.
640+
if(isAngular(ax) && Math.abs(rng[1] - rng[0]) === 360) {
641+
tickVals.pop();
642+
}
643+
625644
// save the last tick as well as first, so we can
626645
// show the exponent only on the last one
627646
ax._tmax = (tickVals[tickVals.length - 1] || {}).value;
@@ -739,8 +758,6 @@ axes.autoTicks = function(ax, roughDTick) {
739758
// being > half of the final unit - so precalculate twice the rough val
740759
var roughX2 = 2 * roughDTick;
741760

742-
// TODO find way to have 'better' first tick on axes with breaks
743-
744761
if(roughX2 > ONEAVGYEAR) {
745762
roughDTick /= ONEAVGYEAR;
746763
base = getBase(10);
@@ -799,9 +816,6 @@ axes.autoTicks = function(ax, roughDTick) {
799816
ax.tick0 = 0;
800817
base = getBase(10);
801818
ax.dtick = roundDTick(roughDTick, base, roundBase10);
802-
803-
// TODO having tick0 = 0 being insider a breaks does not seem
804-
// to matter ...
805819
}
806820

807821
// prevent infinite loops
8.34 KB
Loading

test/jasmine/tests/axes_test.js

+42
Original file line numberDiff line numberDiff line change
@@ -4858,6 +4858,48 @@ describe('Test axes', function() {
48584858
.catch(failTest)
48594859
.then(done);
48604860
});
4861+
4862+
it('should increase dtick when too many (auto) ticks fall into breaks', function(done) {
4863+
var fig = Lib.extendDeep({}, require('@mocks/axes_breaks-finance.json'));
4864+
// break over weekend
4865+
fig.layout.xaxis.breaks[0].enabled = false;
4866+
// break on a single holiday
4867+
fig.layout.xaxis.breaks[1].enabled = false;
4868+
4869+
Plotly.plot(gd, fig)
4870+
.then(function() {
4871+
_assert('base', {
4872+
tickVals: [1483833600000, 1485043200000, 1486252800000]
4873+
});
4874+
})
4875+
.then(function() {
4876+
gd.layout.xaxis.breaks[0].enabled = true;
4877+
gd.layout.xaxis.breaks[1].enabled = true;
4878+
return Plotly.react(gd, gd.data, gd.layout);
4879+
})
4880+
.then(function() {
4881+
_assert('with breaks enabled on x-axis', {
4882+
tickVals: [
4883+
1483531200000, 1484136000000, 1484740800000, 1485345600000,
4884+
1485950400000, 1486555200000, 1487160000000
4885+
]
4886+
});
4887+
})
4888+
.then(function() {
4889+
// a Saturday
4890+
gd.layout.xaxis.tick0 = '2017-01-02';
4891+
// one week
4892+
gd.layout.xaxis.dtick = 7 + 24 * 60 * 60 * 1000;
4893+
return Plotly.react(gd, gd.data, gd.layout);
4894+
})
4895+
.then(function() {
4896+
_assert('honor set tick0/dtick even though they result in few visible ticks', {
4897+
tickVals: [1483488000014]
4898+
});
4899+
})
4900+
.catch(failTest)
4901+
.then(done);
4902+
});
48614903
});
48624904
});
48634905
});

0 commit comments

Comments
 (0)