diff --git a/draftlogs/7420_add.md b/draftlogs/7420_add.md new file mode 100644 index 00000000000..816dec41d27 --- /dev/null +++ b/draftlogs/7420_add.md @@ -0,0 +1,2 @@ + - Add support for ticklabelposition "inside"/"outside" for category axes with `tickson` set to "boundaries" [[#7420](https://github.com/plotly/plotly.js/pull/7420)], + with thanks to @my-tien for the contribution! diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index c293d99b564..18fff21cb40 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -3073,6 +3073,7 @@ function getPosX(d) { // v is a shift perpendicular to the axis function getTickLabelUV(ax) { var ticklabelposition = ax.ticklabelposition || ''; + var tickson = ax.tickson || ''; var has = function(str) { return ticklabelposition.indexOf(str) !== -1; }; @@ -3083,7 +3084,7 @@ function getTickLabelUV(ax) { var isBottom = has('bottom'); var isInside = has('inside'); - var isAligned = isBottom || isLeft || isTop || isRight; + var isAligned = (tickson !== 'boundaries') && (isBottom || isLeft || isTop || isRight); // early return if(!isAligned && !isInside) return [0, 0]; @@ -3167,6 +3168,8 @@ axes.makeTickPath = function(ax, shift, sgn, opts) { */ axes.makeLabelFns = function(ax, shift, angle) { var ticklabelposition = ax.ticklabelposition || ''; + var tickson = ax.tickson || ''; + var has = function(str) { return ticklabelposition.indexOf(str) !== -1; }; @@ -3175,12 +3178,12 @@ axes.makeLabelFns = function(ax, shift, angle) { var isLeft = has('left'); var isRight = has('right'); var isBottom = has('bottom'); - var isAligned = isBottom || isLeft || isTop || isRight; + var isAligned = (tickson !== 'boundaries') && (isBottom || isLeft || isTop || isRight); var insideTickLabels = has('inside'); var labelsOverTicks = (ticklabelposition === 'inside' && ax.ticks === 'inside') || - (!insideTickLabels && ax.ticks === 'outside' && ax.tickson !== 'boundaries'); + (!insideTickLabels && ax.ticks === 'outside' && tickson !== 'boundaries'); var labelStandoff = 0; var labelShift = 0; @@ -3895,6 +3898,8 @@ axes.drawLabels = function(gd, ax, opts) { } } else { var ticklabelposition = ax.ticklabelposition || ''; + var tickson = ax.tickson ||''; + var has = function(str) { return ticklabelposition.indexOf(str) !== -1; }; @@ -3902,7 +3907,7 @@ axes.drawLabels = function(gd, ax, opts) { var isLeft = has('left'); var isRight = has('right'); var isBottom = has('bottom'); - var isAligned = isBottom || isLeft || isTop || isRight; + var isAligned = (tickson !== 'boundaries') && (isBottom || isLeft || isTop || isRight); var pad = !isAligned ? 0 : (ax.tickwidth || 0) + 2 * TEXTPAD; diff --git a/src/plots/cartesian/axis_defaults.js b/src/plots/cartesian/axis_defaults.js index 8c5c75d8832..4531785cd2f 100644 --- a/src/plots/cartesian/axis_defaults.js +++ b/src/plots/cartesian/axis_defaults.js @@ -167,11 +167,11 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, (axType === 'category' || isMultiCategory) && (containerOut.ticks || containerOut.showgrid) ) { - var ticksonDflt; - if(isMultiCategory) ticksonDflt = 'boundaries'; - var tickson = coerce('tickson', ticksonDflt); - if(tickson === 'boundaries') { + if (isMultiCategory) { + coerce('tickson', 'boundaries'); delete containerOut.ticklabelposition; + } else { // category axis + coerce('tickson'); } } diff --git a/src/plots/cartesian/layout_attributes.js b/src/plots/cartesian/layout_attributes.js index 978f545e53e..f1b7bbbe5d6 100644 --- a/src/plots/cartesian/layout_attributes.js +++ b/src/plots/cartesian/layout_attributes.js @@ -663,12 +663,13 @@ module.exports = { dflt: 'outside', editType: 'calc', description: [ - 'Determines where tick labels are drawn with respect to the axis', + 'Determines where tick labels are drawn with respect to the axis.', 'Please note that', - 'top or bottom has no effect on x axes or when `ticklabelmode` is set to *period*.', - 'Similarly', - 'left or right has no effect on y axes or when `ticklabelmode` is set to *period*.', - 'Has no effect on *multicategory* axes or when `tickson` is set to *boundaries*.', + 'top or bottom has no effect on x axes or when `ticklabelmode` is set to *period*', + 'or when `tickson` is set to *boundaries*. Similarly,', + 'left or right has no effect on y axes or when `ticklabelmode` is set to *period*', + 'or when `tickson` is set to *boundaries*.', + 'Has no effect on *multicategory* axes.', 'When used on axes linked by `matches` or `scaleanchor`,', 'no extra padding for inside labels would be added by autorange,', 'so that the scales could match.' diff --git a/test/image/baselines/zz-tickson_boundaries_ticklabelposition.png b/test/image/baselines/zz-tickson_boundaries_ticklabelposition.png new file mode 100644 index 00000000000..5acf8e33d08 Binary files /dev/null and b/test/image/baselines/zz-tickson_boundaries_ticklabelposition.png differ diff --git a/test/image/mocks/zz-tickson_boundaries_ticklabelposition.json b/test/image/mocks/zz-tickson_boundaries_ticklabelposition.json new file mode 100644 index 00000000000..01962a67706 --- /dev/null +++ b/test/image/mocks/zz-tickson_boundaries_ticklabelposition.json @@ -0,0 +1,150 @@ +{ + "data": [ + { + "type": "box", + "x": [ + "day 1", + "day 1", + "day 1", + "day 1", + "day 1", + "day 1", + "day 2", + "day 2", + "day 2", + "day 2", + "day 2", + "day 2" + ], + "y": [0.2, 0.2, 0.6, 1, 0.5, 0.4, 0.2, 0.7, 0.9, 0.1, 0.5, 0.3] + }, + { + "type": "box", + "x": [ + "day 1", + "day 1", + "day 1", + "day 1", + "day 1", + "day 1", + "day 2", + "day 2", + "day 2", + "day 2", + "day 2", + "day 2" + ], + "y": [0.1, 0.3, 0.1, 0.9, 0.6, 0.6, 0.9, 1, 0.3, 0.6, 0.8, 0.5] + }, + { + "type": "box", + "x": [ + "day 1", + "day 1", + "day 1", + "day 1", + "day 1", + "day 1", + "day 2", + "day 2", + "day 2", + "day 2", + "day 2", + "day 2" + ], + "y": [0.6, 0.7, 0.3, 0.6, 0, 0.5, 0.7, 0.9, 0.5, 0.8, 0.7, 0.2] + }, + + { + "type": "bar", + "x": [1, 2, 1], + "y": ["apples", "bananas", "clementines"], + "orientation": "h", + "xaxis": "x2", + "yaxis": "y2" + }, + { + "type": "bar", + "x": [1.3, 2.2, 0.8], + "y": ["apples", "bananas", "clementines"], + "orientation": "h", + "xaxis": "x2", + "yaxis": "y2" + }, + { + "type": "bar", + "x": [3, 3.2, 1.8], + "y": ["apples", "bananas", "clementines"], + "orientation": "h", + "xaxis": "x2", + "yaxis": "y2" + }, + + { + "type": "bar", + "name": "with dtick !== 1", + "x": ["a", "b", "c", "d", "e", "f", "g", "h"], + "y": [1, 2, 1, 2, 1, 3, 4, 1], + "xaxis": "x3", + "yaxis": "y3" + }, + + { + "mode": "markers", + "marker": { "symbol": "square" }, + "name": "with overlapping tick labels", + "x": ["A very long title", "short", "Another very long title"], + "y": [0, 10, 2], + "xaxis": "x4", + "yaxis": "y4" + } + ], + "layout": { + "title": { + "text": "Although some ticklabelpositions have a side specified,
all category labels are expected to be centered." + }, + "boxmode": "group", + "grid": { + "rows": 4, + "columns": 1, + "pattern": "independent", + "ygap": 0.2 + }, + "xaxis": { + "ticklabelposition": "inside right", + "ticks": "outside", + "tickson": "boundaries", + "gridcolor": "white", + "gridwidth": 4 + }, + "yaxis2": { + "ticks": "inside", + "ticklabelposition": "inside top", + "tickson": "boundaries", + "gridcolor": "white", + "gridwidth": 4 + }, + "xaxis3": { + "ticks": "inside", + "ticklabelposition": "inside left", + "tickson": "boundaries", + "gridcolor": "white", + "gridwidth": 4, + "dtick": 2 + }, + "xaxis4": { + "domain": [0.22, 0.78], + "ticks": "outside", + "ticklabelposition": "inside", + "ticklen": 20, + "tickson": "boundaries", + "gridcolor": "white", + "gridwidth": 4 + }, + "plot_bgcolor": "lightgrey", + "showlegend": false, + "width": 500, + "height": 800, + "margin": { "b": 140 } + } +} diff --git a/test/plot-schema.json b/test/plot-schema.json index 403428a1457..25256d4b2a4 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -14711,7 +14711,7 @@ ] }, "ticklabelposition": { - "description": "Determines where tick labels are drawn with respect to the axis Please note that top or bottom has no effect on x axes or when `ticklabelmode` is set to *period*. Similarly left or right has no effect on y axes or when `ticklabelmode` is set to *period*. Has no effect on *multicategory* axes or when `tickson` is set to *boundaries*. When used on axes linked by `matches` or `scaleanchor`, no extra padding for inside labels would be added by autorange, so that the scales could match.", + "description": "Determines where tick labels are drawn with respect to the axis. Please note that top or bottom has no effect on x axes or when `ticklabelmode` is set to *period* or when `tickson` is set to *boundaries*. Similarly, left or right has no effect on y axes or when `ticklabelmode` is set to *period* or when `tickson` is set to *boundaries*. Has no effect on *multicategory* axes. When used on axes linked by `matches` or `scaleanchor`, no extra padding for inside labels would be added by autorange, so that the scales could match.", "dflt": "outside", "editType": "calc", "valType": "enumerated", @@ -15955,7 +15955,7 @@ ] }, "ticklabelposition": { - "description": "Determines where tick labels are drawn with respect to the axis Please note that top or bottom has no effect on x axes or when `ticklabelmode` is set to *period*. Similarly left or right has no effect on y axes or when `ticklabelmode` is set to *period*. Has no effect on *multicategory* axes or when `tickson` is set to *boundaries*. When used on axes linked by `matches` or `scaleanchor`, no extra padding for inside labels would be added by autorange, so that the scales could match.", + "description": "Determines where tick labels are drawn with respect to the axis. Please note that top or bottom has no effect on x axes or when `ticklabelmode` is set to *period* or when `tickson` is set to *boundaries*. Similarly, left or right has no effect on y axes or when `ticklabelmode` is set to *period* or when `tickson` is set to *boundaries*. Has no effect on *multicategory* axes. When used on axes linked by `matches` or `scaleanchor`, no extra padding for inside labels would be added by autorange, so that the scales could match.", "dflt": "outside", "editType": "calc", "valType": "enumerated", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy