diff --git a/draftlogs/6970_fix.md b/draftlogs/6970_fix.md new file mode 100644 index 00000000000..96922b1925c --- /dev/null +++ b/draftlogs/6970_fix.md @@ -0,0 +1,2 @@ +- Fix positioning of multi-line axis titles with `standoff` [[#6970](https://github.com/plotly/plotly.js/pull/6970)], + with thanks to @my-tien for the contribution! diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 1386cb8418c..eb71c1926df 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -4060,9 +4060,7 @@ function approxTitleDepth(ax) { var fontSize = ax.title.font.size; var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length; if(ax.title.hasOwnProperty('standoff')) { - return extraLines ? - fontSize * (CAP_SHIFT + (extraLines * LINE_SPACING)) : - fontSize * CAP_SHIFT; + return fontSize * (CAP_SHIFT + (extraLines * LINE_SPACING)); } else { return extraLines ? fontSize * (extraLines + 1) * LINE_SPACING : @@ -4093,9 +4091,20 @@ function drawTitle(gd, ax) { var axLetter = axId.charAt(0); var fontSize = ax.title.font.size; var titleStandoff; + var extraLines = (ax.title.text.match(svgTextUtils.BR_TAG_ALL) || []).length; if(ax.title.hasOwnProperty('standoff')) { - titleStandoff = ax._depth + ax.title.standoff + approxTitleDepth(ax); + // With ax._depth the initial drawing baseline is at the outer axis border (where the + // ticklabels are drawn). Since the title text will be drawn above the baseline, + // bottom/right axes must be shifted by 1 text line to draw below ticklabels instead of on + // top of them, whereas for top/left axes, the first line would be drawn + // before the ticklabels, but we need an offset for the descender portion of the first line + // and all subsequent lines. + if(ax.side === 'bottom' || ax.side === 'right') { + titleStandoff = ax._depth + ax.title.standoff + fontSize * CAP_SHIFT; + } else if(ax.side === 'top' || ax.side === 'left') { + titleStandoff = ax._depth + ax.title.standoff + fontSize * (MID_SHIFT + (extraLines * LINE_SPACING)); + } } else { var isInside = insideTicklabelposition(ax); diff --git a/test/image/baselines/axis-title-standoff.png b/test/image/baselines/axis-title-standoff.png index 1464feac871..59fdbec4127 100644 Binary files a/test/image/baselines/axis-title-standoff.png and b/test/image/baselines/axis-title-standoff.png differ diff --git a/test/image/baselines/line_scatter_change_side.png b/test/image/baselines/line_scatter_change_side.png index faed272b20f..ea9e7d6e1c5 100644 Binary files a/test/image/baselines/line_scatter_change_side.png and b/test/image/baselines/line_scatter_change_side.png differ diff --git a/test/image/baselines/line_scatter_change_side_shrunk.png b/test/image/baselines/line_scatter_change_side_shrunk.png index 6aff06c20d7..9a4eee7a117 100644 Binary files a/test/image/baselines/line_scatter_change_side_shrunk.png and b/test/image/baselines/line_scatter_change_side_shrunk.png differ diff --git a/test/image/baselines/line_scatter_regular_side.png b/test/image/baselines/line_scatter_regular_side.png index 570f5ca7521..cac503c85d4 100644 Binary files a/test/image/baselines/line_scatter_regular_side.png and b/test/image/baselines/line_scatter_regular_side.png differ diff --git a/test/image/baselines/line_scatter_regular_side_shrunk.png b/test/image/baselines/line_scatter_regular_side_shrunk.png index c6c9b2b636d..422c0160080 100644 Binary files a/test/image/baselines/line_scatter_regular_side_shrunk.png and b/test/image/baselines/line_scatter_regular_side_shrunk.png differ diff --git a/test/image/baselines/mult-yaxes-simple.png b/test/image/baselines/mult-yaxes-simple.png index ee5345f52fb..549917d680a 100644 Binary files a/test/image/baselines/mult-yaxes-simple.png and b/test/image/baselines/mult-yaxes-simple.png differ diff --git a/test/image/baselines/petrophysics.png b/test/image/baselines/petrophysics.png index 6edfcd9305a..aba9c94bad0 100644 Binary files a/test/image/baselines/petrophysics.png and b/test/image/baselines/petrophysics.png differ diff --git a/test/image/baselines/zz-axis_title_standoff0.png b/test/image/baselines/zz-axis_title_standoff0.png new file mode 100644 index 00000000000..4f6f3609cfe Binary files /dev/null and b/test/image/baselines/zz-axis_title_standoff0.png differ diff --git a/test/image/mocks/axis-title-standoff.json b/test/image/mocks/axis-title-standoff.json index 30789e6dd3e..40900aabaaa 100644 --- a/test/image/mocks/axis-title-standoff.json +++ b/test/image/mocks/axis-title-standoff.json @@ -26,7 +26,7 @@ }, "yaxis": { "title": { - "text": "Y
Axis (standoff:8)", + "text": "Y
Axis (standoff:0)", "standoff": 0, "font": {"size": 8} }, diff --git a/test/image/mocks/zz-axis_title_standoff0.json b/test/image/mocks/zz-axis_title_standoff0.json new file mode 100644 index 00000000000..0ef01d7b405 --- /dev/null +++ b/test/image/mocks/zz-axis_title_standoff0.json @@ -0,0 +1,155 @@ +{ + "data": [ + { + "mode": "markers", + "x": [ + 100, + 200, + 300, + 400, + 500 + ], + "y": [ + 200, + 300, + 400, + 500, + 600 + ], + "type": "scatter" + }, + { + "mode": "markers", + "x": [ + 100, + 200, + 300, + 400, + 500 + ], + "y": [ + 200, + 300, + 400, + 500, + 600 + ], + "type": "scatter", + "xaxis": "x2", + "yaxis": "y2" + }, + { + "mode": "markers", + "x": [ + 100, + 200, + 300, + 400, + 500 + ], + "y": [ + 200, + 300, + 400, + 500, + 600 + ], + "type": "scatter", + "xaxis": "x3", + "yaxis": "y3" + }, + { + "mode": "markers", + "x": [ + 100, + 200, + 300, + 400, + 500 + ], + "y": [ + 200, + 300, + 400, + 500, + 600 + ], + "type": "scatter", + "xaxis": "x4", + "yaxis": "y4" + } + ], + "layout": { + "width": 800, + "legend": { + "visible": false + }, + "grid": { + "rows": 2, + "columns": 2, + "pattern": "independent", + "xgap": 0.4 + }, + "xaxis": { + "title": { + "text": "______xaxis______", + "standoff": 0 + }, + "side": "top", + "automargin": true + }, + "xaxis3": { + "title": { + "text": "¯¯¯¯¯¯xaxis3¯¯¯¯¯¯", + "standoff": 0 + }, + "automargin": true + }, + "yaxis": { + "title": { + "text": "______yaxis______", + "standoff": 0 + }, + "automargin": true + }, + "yaxis3": { + "title": { + "text": "¯¯¯¯¯¯yaxis3¯¯¯¯¯¯", + "standoff": 0 + }, + "side": "right", + "automargin": true + }, + "xaxis2": { + "title": { + "text": "xaxis2
some
more
______text______", + "standoff": 0 + }, + "side": "top", + "automargin": true + }, + "xaxis4": { + "title": { + "text": "¯¯¯¯¯¯xaxis4¯¯¯¯¯¯
some
more
text", + "standoff": 0 + }, + "side": "bottom", + "automargin": true + }, + "yaxis2": { + "title": { + "text": "¯¯¯¯¯¯yaxis2¯¯¯¯¯¯
some
more
text", + "standoff": 0 + }, + "side": "right", + "automargin": true + }, + "yaxis4": { + "title": { + "text": "yaxis4
some
more
______text______", + "standoff": 0 + }, + "automargin": true + } + } +}