diff --git a/draftlogs/7735_change.md b/draftlogs/7735_change.md new file mode 100644 index 00000000000..5ad1393e647 --- /dev/null +++ b/draftlogs/7735_change.md @@ -0,0 +1 @@ + - Change ticklabelindex to also be effective when no minor ticks are visible. [[#7735](https://github.com/plotly/plotly.js/pull/7735)] diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 38a8a7a8909..d934f1b4e5c 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -603,7 +603,7 @@ function autoShiftMonthBins(binStart, data, dtick, dataMin, calendar) { // ensure we have minor tick0 and dtick calculated axes.prepMinorTicks = function(mockAx, ax, opts) { - if(!ax.minor.dtick) { + if(!ax.minor?.dtick) { delete mockAx.dtick; var hasMajor = ax.dtick && isNumeric(ax._tmin); var mockMinorRange; @@ -690,7 +690,7 @@ axes.prepMinorTicks = function(mockAx, ax, opts) { // put back the original range, to use to find the full set of minor ticks mockAx.range = ax.range; } - if(ax.minor._tick0Init === undefined) { + if(ax.minor?._tick0Init === undefined) { // ensure identical tick0 mockAx.tick0 = ax.tick0; } @@ -973,21 +973,23 @@ axes.calcTicks = function calcTicks(ax, opts) { var allTicklabelVals = []; var hasMinor = ax.minor && (ax.minor.ticks || ax.minor.showgrid); + // minor ticks should be calculated if they are visible or if ticklabelindex is set because then + // the labels are placed at minor ticks (even if invisible) instead of major ticks. + var calcMinor = hasMinor || ticklabelIndex; // calc major first - for(var major = 1; major >= (hasMinor ? 0 : 1); major--) { + for(var major = 1; major >= (calcMinor ? 0 : 1); major--) { var isMinor = !major; if(major) { ax._dtickInit = ax.dtick; ax._tick0Init = ax.tick0; - } else { + } else if (hasMinor) { ax.minor._dtickInit = ax.minor.dtick; ax.minor._tick0Init = ax.minor.tick0; } - var mockAx = major ? ax : Lib.extendFlat({}, ax, ax.minor); - + var mockAx = major ? ax : Lib.extendFlat({}, ax, hasMinor ? ax.minor : {"minor": {}}); if(isMinor) { axes.prepMinorTicks(mockAx, ax, opts); } else { @@ -1074,7 +1076,7 @@ axes.calcTicks = function calcTicks(ax, opts) { } } - if(major && isPeriod) { + if((major || calcMinor) && isPeriod) { // add one item to label period before tick0 x = axes.tickIncrement(x, dtick, !axrev, calendar); majorId--; @@ -1298,9 +1300,14 @@ axes.calcTicks = function calcTicks(ax, opts) { } else { lastVisibleHead = ax._prevDateHead; t = setTickLabel(ax, tickVals[i]); - if(tickVals[i].skipLabel || - ticklabelIndex && allTicklabelVals.indexOf(tickVals[i]) === -1) { - hideLabel(t); + if (ticklabelIndex) { + if (allTicklabelVals.indexOf(tickVals[i]) === -1) { + hideLabel(t); + } + } else { + if (tickVals[i].skipLabel) { + hideLabel(t); + } } ticksOut.push(t); diff --git a/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-dtick.png b/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-dtick.png new file mode 100644 index 00000000000..d5a5bc78c7b Binary files /dev/null and b/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-dtick.png differ diff --git a/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-one-label.png b/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-one-label.png new file mode 100644 index 00000000000..35c50e3af79 Binary files /dev/null and b/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-one-label.png differ diff --git a/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-ticklabelstep.png b/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-ticklabelstep.png new file mode 100644 index 00000000000..0b90011dafc Binary files /dev/null and b/test/image/baselines/zz-ticklabelindex-hidden-minor-ticks-ticklabelstep.png differ diff --git a/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-dtick.json b/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-dtick.json new file mode 100644 index 00000000000..99b03aedf53 --- /dev/null +++ b/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-dtick.json @@ -0,0 +1,28 @@ +{ + "data": [ + { + "showlegend": false, + "x": [ + "2023-01-01", + "2024-01-01", + "2025-01-01", + "2026-01-01", + "2027-01-01" + ], + "type": "scatter" + } + ], + "layout": { + "width": 700, + "xaxis": { + "ticklen": 20, + "ticklabelindex": -1, + "tickformat": "%Y", + "ticklabelmode": "period", + "dtick": "M24" + }, + "title": { + "text": "Should display 2 ticks and labels 2023 and 2025 to the left of them." + } + } + } diff --git a/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-one-label.json b/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-one-label.json new file mode 100644 index 00000000000..d29a029ab25 --- /dev/null +++ b/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-one-label.json @@ -0,0 +1,27 @@ +{ + "data": [ + { + "showlegend": false, + "x": [ + "2023-01-01", + "2024-01-01", + "2025-01-01", + "2026-01-01" + ], + "type": "scatter" + } + ], + "layout": { + "width": 700, + "xaxis": { + "ticklen": 20, + "ticklabelindex": -2, + "tickformat": "%Y", + "ticklabelmode": "period", + "dtick": "M24" + }, + "title": { + "text": "Should display a label at 2024" + } + } + } diff --git a/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-ticklabelstep.json b/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-ticklabelstep.json new file mode 100644 index 00000000000..a42823afcd4 --- /dev/null +++ b/test/image/mocks/zz-ticklabelindex-hidden-minor-ticks-ticklabelstep.json @@ -0,0 +1,29 @@ +{ + "data": [ + { + "showlegend": false, + "x": [ + "2023-01-01", + "2024-01-01", + "2025-01-01", + "2026-01-01", + "2027-01-01" + ], + "type": "scatter" + } + ], + "layout": { + "width": 700, + "xaxis": { + "ticklen": 20, + "ticklabelindex": -1, + "tickformat": "%Y", + "ticklabelmode": "period", + "ticklabelstep": 2, + "dtick": "M12" + }, + "title": { + "text": "Should display yearly ticks with labels at 2023 and 2025" + } + } + }