Skip to content

Commit 74a8f9c

Browse files
authored
Merge pull request #6088 from plotly/ticklabeljump
Implement `ticklabelstep` on 2D axes & colorbars
2 parents 6b2c637 + d834bbb commit 74a8f9c

25 files changed

+496
-5
lines changed

draftlogs/6088_add.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Implement `ticklabelstep` on 2D axes & colorbars [[#6088](https://github.com/plotly/plotly.js/pull/6088)]

src/components/colorbar/attributes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ module.exports = overrideAll({
166166
ticklen: axesAttrs.ticklen,
167167
tickwidth: axesAttrs.tickwidth,
168168
tickcolor: axesAttrs.tickcolor,
169+
ticklabelstep: axesAttrs.ticklabelstep,
169170
showticklabels: axesAttrs.showticklabels,
170171
tickfont: fontAttrs({
171172
description: 'Sets the color bar\'s tick label font'

src/components/colorbar/draw.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,7 @@ function mockColorBarAxis(gd, opts, zrange) {
933933
showticklabels: opts.showticklabels,
934934
ticklabelposition: opts.ticklabelposition,
935935
ticklabeloverflow: opts.ticklabeloverflow,
936+
ticklabelstep: opts.ticklabelstep,
936937
tickfont: opts.tickfont,
937938
tickangle: opts.tickangle,
938939
tickformat: opts.tickformat,

src/plots/cartesian/axes.js

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,8 @@ axes.calcTicks = function calcTicks(ax, opts) {
803803
var minRange = Math.min(rng[0], rng[1]);
804804
var maxRange = Math.max(rng[0], rng[1]);
805805

806-
var isDLog = (ax.type === 'log') && !(isNumeric(ax.dtick) || ax.dtick.charAt(0) === 'L');
806+
var numDtick = isNumeric(ax.dtick);
807+
var isDLog = (ax.type === 'log') && !(numDtick || ax.dtick.charAt(0) === 'L');
807808
var isPeriod = ax.ticklabelmode === 'period';
808809

809810
// find the first tick
@@ -834,13 +835,36 @@ axes.calcTicks = function calcTicks(ax, opts) {
834835
x = axes.tickIncrement(x, ax.dtick, !axrev, ax.calendar);
835836
}
836837

838+
var ticklabelstep = ax.ticklabelstep;
839+
837840
var maxTicks = Math.max(1000, ax._length || 0);
838841
var tickVals = [];
839842
var xPrevious = null;
843+
844+
var dTick;
845+
if(numDtick) {
846+
dTick = ax.dtick;
847+
} else {
848+
if(ax.type === 'date') {
849+
if(typeof ax.dtick === 'string' && ax.dtick.charAt(0) === 'M') {
850+
dTick = ONEAVGMONTH * ax.dtick.substring(1);
851+
}
852+
} else {
853+
dTick = ax._roughDTick;
854+
}
855+
}
856+
857+
var id = Math.round((
858+
ax.r2l(x) -
859+
ax.r2l(ax.tick0)
860+
) / dTick) - 1;
861+
840862
for(;
841863
(axrev) ? (x >= endTick) : (x <= endTick);
842864
x = axes.tickIncrement(x, ax.dtick, axrev, ax.calendar)
843865
) {
866+
id++;
867+
844868
if(ax.rangebreaks) {
845869
if(!axrev) {
846870
if(x < startTick) continue;
@@ -858,10 +882,16 @@ axes.calcTicks = function calcTicks(ax, opts) {
858882
minor = true;
859883
}
860884

861-
tickVals.push({
885+
var obj = {
862886
minor: minor,
863887
value: x
864-
});
888+
};
889+
890+
if(ticklabelstep > 1 && id % ticklabelstep) {
891+
obj.skipLabel = true;
892+
}
893+
894+
tickVals.push(obj);
865895
}
866896

867897
if(isPeriod) positionPeriodTicks(tickVals, ax, ax._definedDelta);
@@ -914,12 +944,20 @@ axes.calcTicks = function calcTicks(ax, opts) {
914944
ax._prevDateHead = '';
915945
ax._inCalcTicks = true;
916946

947+
var lastVisibleHead;
948+
var hideLabel = function(tick) {
949+
tick.text = ' '; // don't use an empty string here which can confuse automargin (issue 5132)
950+
ax._prevDateHead = lastVisibleHead;
951+
};
952+
917953
var ticksOut = [];
918954
var t, p;
919955
for(i = 0; i < tickVals.length; i++) {
920956
var _minor = tickVals[i].minor;
921957
var _value = tickVals[i].value;
922958

959+
lastVisibleHead = ax._prevDateHead;
960+
923961
t = axes.tickText(
924962
ax,
925963
_value,
@@ -934,11 +972,14 @@ axes.calcTicks = function calcTicks(ax, opts) {
934972
if(p > maxRange) t.periodX = maxRange;
935973
if(p < minRange) t.periodX = minRange;
936974

937-
t.text = ' '; // don't use an empty string here which can confuse automargin (issue 5132)
938-
ax._prevDateHead = '';
975+
hideLabel(t);
939976
}
940977
}
941978

979+
if(tickVals[i].skipLabel) {
980+
hideLabel(t);
981+
}
982+
942983
ticksOut.push(t);
943984
}
944985

@@ -2966,6 +3007,7 @@ axes.drawLabels = function(gd, ax, opts) {
29663007
var axId = ax._id;
29673008
var axLetter = axId.charAt(0);
29683009
var cls = opts.cls || axId + 'tick';
3010+
29693011
var vals = opts.vals;
29703012

29713013
var labelFns = opts.labelFns;

src/plots/cartesian/layout_attributes.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,20 @@ module.exports = {
412412
'To set ticks every 4 years, set `dtick` to *M48*'
413413
].join(' ')
414414
},
415+
ticklabelstep: {
416+
valType: 'integer',
417+
min: 1,
418+
dflt: 1,
419+
editType: 'ticks',
420+
description: [
421+
'Sets the spacing between tick labels as compared to the spacing between ticks.',
422+
'A value of 1 (default) means each tick gets a label.',
423+
'A value of 2 means shows every 2nd label.',
424+
'A larger value n means only every nth tick is labeled.',
425+
'`tick0` determines which labels are shown.',
426+
'Not implemented for axes with `type` *log* or *multicategory*, or when `tickmode` is *array*.'
427+
].join(' ')
428+
},
415429
tickvals: {
416430
valType: 'data_array',
417431
editType: 'ticks',

src/plots/cartesian/tick_label_defaults.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ module.exports = function handleTickLabelDefaults(containerIn, containerOut, coe
2828
color: dfltFontColor
2929
});
3030

31+
if(
32+
!options.noTicklabelstep &&
33+
axType !== 'multicategory' &&
34+
axType !== 'log'
35+
) {
36+
coerce('ticklabelstep');
37+
}
38+
3139
if(!options.noAng) coerce('tickangle');
3240

3341
if(axType !== 'category') {

src/plots/gl3d/layout/axis_defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) {
4343
showGrid: true,
4444
noTickson: true,
4545
noTicklabelmode: true,
46+
noTicklabelstep: true,
4647
noTicklabelposition: true,
4748
noTicklabeloverflow: true,
4849
bgColor: options.bgColor,

src/plots/polar/layout_attributes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var axisTickAttrs = overrideAll({
3232
ticklen: axesAttrs.ticklen,
3333
tickwidth: axesAttrs.tickwidth,
3434
tickcolor: axesAttrs.tickcolor,
35+
ticklabelstep: axesAttrs.ticklabelstep,
3536
showticklabels: axesAttrs.showticklabels,
3637
showtickprefix: axesAttrs.showtickprefix,
3738
tickprefix: axesAttrs.tickprefix,

src/plots/smith/layout_defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ function handleDefaults(contIn, contOut, coerce, opts) {
8383
}
8484

8585
handleTickLabelDefaults(axIn, axOut, coerceAxis, axOut.type, {
86+
noTicklabelstep: true,
8687
noAng: !isRealAxis,
8788
noExp: true,
8889
font: {

src/plots/ternary/layout_attributes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ var ternaryAxesAttrs = {
2525
ticklen: axesAttrs.ticklen,
2626
tickwidth: axesAttrs.tickwidth,
2727
tickcolor: axesAttrs.tickcolor,
28+
ticklabelstep: axesAttrs.ticklabelstep,
2829
showticklabels: axesAttrs.showticklabels,
2930
showtickprefix: axesAttrs.showtickprefix,
3031
tickprefix: axesAttrs.tickprefix,

0 commit comments

Comments
 (0)