Skip to content

Position title after legend width calculated #6725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 22, 2023
4 changes: 4 additions & 0 deletions draftlogs/6725_fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
```
- Fix horizontal title alignment [[#6668](https://github.com/plotly/plotly.js/issues/6668)]
- Fix single-point histogram when user has provided bin widths [[#6661](https://github.com/plotly/plotly.js/issues/6661)]
```
39 changes: 32 additions & 7 deletions src/components/legend/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,30 @@ module.exports = function draw(gd, opts) {
}
};

// After legend dimensions are calculated the title can be aligned horizontally left, center, right
function horizontalAlignTitle(titleEl, legendObj, bw) {
if((legendObj.title.side !== 'top center') && (legendObj.title.side !== 'top right')) return;

var font = legendObj.title.font;
var lineHeight = font.size * LINE_SPACING;
var titleOffset = 0;
var textNode = titleEl.node();

var width = Drawing.bBox(textNode).width; // width of the title text

if(legendObj.title.side === 'top center') {
titleOffset = 0.5 * (legendObj._width - 2 * bw - 2 * constants.titlePad - width);
} else if(legendObj.title.side === 'top right') {
titleOffset = legendObj._width - 2 * bw - 2 * constants.titlePad - width;
}

svgTextUtils.positionText(titleEl,
bw + constants.titlePad + titleOffset,
bw + lineHeight
);
}


function drawOne(gd, opts) {
var legendObj = opts || {};

Expand Down Expand Up @@ -148,8 +172,9 @@ function drawOne(gd, opts) {
var title = legendObj.title;
legendObj._titleWidth = 0;
legendObj._titleHeight = 0;
var titleEl;
if(title.text) {
var titleEl = Lib.ensureSingle(scrollBox, 'text', legendId + 'titletext');
titleEl = Lib.ensureSingle(scrollBox, 'text', legendId + 'titletext');
titleEl.attr('text-anchor', 'start')
.call(Drawing.font, title.font)
.text(title.text);
Expand Down Expand Up @@ -193,6 +218,11 @@ function drawOne(gd, opts) {
var isPaperX = legendObj.xref === 'paper';
var isPaperY = legendObj.yref === 'paper';

// re-calculate title position after legend width is derived. To allow for horizontal alignment
if(title.text) {
horizontalAlignTitle(titleEl, legendObj, bw);
}

if(!inHover) {
var lx, ly;

Expand Down Expand Up @@ -661,18 +691,13 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
// approximation to height offset to center the font
// to avoid getBoundingClientRect
if(aTitle === MAIN_TITLE) {
var titleOffset = 0;
if(legendObj.title.side === 'left') {
// add extra space between legend title and itmes
width += constants.itemGap * 2;
} else if(legendObj.title.side === 'top center') {
if(legendObj._width) titleOffset = 0.5 * (legendObj._width - 2 * bw - 2 * constants.titlePad - width);
} else if(legendObj.title.side === 'top right') {
if(legendObj._width) titleOffset = legendObj._width - 2 * bw - 2 * constants.titlePad - width;
}

svgTextUtils.positionText(textEl,
bw + constants.titlePad + titleOffset,
bw + constants.titlePad,
bw + lineHeight
);
} else { // legend item
Expand Down
4 changes: 3 additions & 1 deletion src/traces/histogram/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,8 +308,10 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {

// Edge case: single-valued histogram overlaying others
// Use them all together to calculate the bin size for the single-valued one
// Don't re-calculate bin width if user manually specified it (checing in bingroup=='' or xbins is defined)
if(isOverlay && !Registry.traceIs(trace, '2dMap') && newBinSpec._dataSpan === 0 &&
pa.type !== 'category' && pa.type !== 'multicategory') {
pa.type !== 'category' && pa.type !== 'multicategory' &&
trace.bingroup === '' && (typeof trace.xbins === 'undefined')) {
// Several single-valued histograms! Stop infinite recursion,
// just return an extra flag that tells handleSingleValueOverlays
// to sort out this trace too
Expand Down
Binary file modified test/image/baselines/legend_horizontal_one_row.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/image/mocks/legend_horizontal_one_row.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
}
],
"layout": {
"height": 300,
"title": {"text": "Average Distribution per Month"},
"legend": { "orientation": "h", "title": { "text": "Legend Title", "side": "top center" }}
}
Expand Down
48 changes: 48 additions & 0 deletions test/image/mocks/zz_histogram_overlay-1point-date.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"data": [
{
"x": ["2023-05-22 09:29:56.00"],
"opacity": 1,
"type": "histogram",
"name": "Results B",
"marker": {
"color": "rgba(0, 255, 0, .2)",
"line": {
"color": "rgba(0, 255, 0, 1)",
"width": 2
}
},
"xbins": {
"size": "M1",
"start": "2023-05-01",
"end": "2023-07-01"
}
},
{
"x": ["2023-05-21 09:29:56.00", "2023-05-26 09:29:56.00", "2023-06-21 09:29:56.00"],
"opacity": 1,
"type": "histogram",
"name": "Results A",
"marker": {
"color": "rgba(0, 0, 255, .2)",
"line": {
"color": "rgba(0, 0, 255, 1)",
"width": 2
}
},
"xbins": {
"size": "M1",
"start": "2023-05-01",
"end": "2023-07-01"
}
}
],
"layout": {
"barmode": "overlay",
"title": { "text": "Sampled Results" },
"xaxis": {
"title": { "text": "Date" }
},
"yaxis": { "title": { "text": "Count" } }
}
}