Skip to content

Commit 6825695

Browse files
authored
Merge pull request #6725 from 28raining/fix-legend-title-h-align
Position title after legend width calculated
2 parents f316a7a + b7a98e2 commit 6825695

File tree

7 files changed

+88
-8
lines changed

7 files changed

+88
-8
lines changed

draftlogs/6725_fix.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```
2+
- Fix horizontal title alignment [[#6668](https://github.com/plotly/plotly.js/issues/6668)]
3+
- Fix single-point histogram when user has provided bin widths [[#6661](https://github.com/plotly/plotly.js/issues/6661)]
4+
```

src/components/legend/draw.js

+32-7
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ module.exports = function draw(gd, opts) {
5454
}
5555
};
5656

57+
// After legend dimensions are calculated the title can be aligned horizontally left, center, right
58+
function horizontalAlignTitle(titleEl, legendObj, bw) {
59+
if((legendObj.title.side !== 'top center') && (legendObj.title.side !== 'top right')) return;
60+
61+
var font = legendObj.title.font;
62+
var lineHeight = font.size * LINE_SPACING;
63+
var titleOffset = 0;
64+
var textNode = titleEl.node();
65+
66+
var width = Drawing.bBox(textNode).width; // width of the title text
67+
68+
if(legendObj.title.side === 'top center') {
69+
titleOffset = 0.5 * (legendObj._width - 2 * bw - 2 * constants.titlePad - width);
70+
} else if(legendObj.title.side === 'top right') {
71+
titleOffset = legendObj._width - 2 * bw - 2 * constants.titlePad - width;
72+
}
73+
74+
svgTextUtils.positionText(titleEl,
75+
bw + constants.titlePad + titleOffset,
76+
bw + lineHeight
77+
);
78+
}
79+
80+
5781
function drawOne(gd, opts) {
5882
var legendObj = opts || {};
5983

@@ -148,8 +172,9 @@ function drawOne(gd, opts) {
148172
var title = legendObj.title;
149173
legendObj._titleWidth = 0;
150174
legendObj._titleHeight = 0;
175+
var titleEl;
151176
if(title.text) {
152-
var titleEl = Lib.ensureSingle(scrollBox, 'text', legendId + 'titletext');
177+
titleEl = Lib.ensureSingle(scrollBox, 'text', legendId + 'titletext');
153178
titleEl.attr('text-anchor', 'start')
154179
.call(Drawing.font, title.font)
155180
.text(title.text);
@@ -193,6 +218,11 @@ function drawOne(gd, opts) {
193218
var isPaperX = legendObj.xref === 'paper';
194219
var isPaperY = legendObj.yref === 'paper';
195220

221+
// re-calculate title position after legend width is derived. To allow for horizontal alignment
222+
if(title.text) {
223+
horizontalAlignTitle(titleEl, legendObj, bw);
224+
}
225+
196226
if(!inHover) {
197227
var lx, ly;
198228

@@ -661,18 +691,13 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
661691
// approximation to height offset to center the font
662692
// to avoid getBoundingClientRect
663693
if(aTitle === MAIN_TITLE) {
664-
var titleOffset = 0;
665694
if(legendObj.title.side === 'left') {
666695
// add extra space between legend title and itmes
667696
width += constants.itemGap * 2;
668-
} else if(legendObj.title.side === 'top center') {
669-
if(legendObj._width) titleOffset = 0.5 * (legendObj._width - 2 * bw - 2 * constants.titlePad - width);
670-
} else if(legendObj.title.side === 'top right') {
671-
if(legendObj._width) titleOffset = legendObj._width - 2 * bw - 2 * constants.titlePad - width;
672697
}
673698

674699
svgTextUtils.positionText(textEl,
675-
bw + constants.titlePad + titleOffset,
700+
bw + constants.titlePad,
676701
bw + lineHeight
677702
);
678703
} else { // legend item

src/traces/histogram/calc.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,10 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
308308

309309
// Edge case: single-valued histogram overlaying others
310310
// Use them all together to calculate the bin size for the single-valued one
311+
// Don't re-calculate bin width if user manually specified it (checing in bingroup=='' or xbins is defined)
311312
if(isOverlay && !Registry.traceIs(trace, '2dMap') && newBinSpec._dataSpan === 0 &&
312-
pa.type !== 'category' && pa.type !== 'multicategory') {
313+
pa.type !== 'category' && pa.type !== 'multicategory' &&
314+
trace.bingroup === '' && (typeof trace.xbins === 'undefined')) {
313315
// Several single-valued histograms! Stop infinite recursion,
314316
// just return an extra flag that tells handleSingleValueOverlays
315317
// to sort out this trace too
Loading
Loading

test/image/mocks/legend_horizontal_one_row.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
}
2121
],
2222
"layout": {
23+
"height": 300,
2324
"title": {"text": "Average Distribution per Month"},
2425
"legend": { "orientation": "h", "title": { "text": "Legend Title", "side": "top center" }}
2526
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"data": [
3+
{
4+
"x": ["2023-05-22 09:29:56.00"],
5+
"opacity": 1,
6+
"type": "histogram",
7+
"name": "Results B",
8+
"marker": {
9+
"color": "rgba(0, 255, 0, .2)",
10+
"line": {
11+
"color": "rgba(0, 255, 0, 1)",
12+
"width": 2
13+
}
14+
},
15+
"xbins": {
16+
"size": "M1",
17+
"start": "2023-05-01",
18+
"end": "2023-07-01"
19+
}
20+
},
21+
{
22+
"x": ["2023-05-21 09:29:56.00", "2023-05-26 09:29:56.00", "2023-06-21 09:29:56.00"],
23+
"opacity": 1,
24+
"type": "histogram",
25+
"name": "Results A",
26+
"marker": {
27+
"color": "rgba(0, 0, 255, .2)",
28+
"line": {
29+
"color": "rgba(0, 0, 255, 1)",
30+
"width": 2
31+
}
32+
},
33+
"xbins": {
34+
"size": "M1",
35+
"start": "2023-05-01",
36+
"end": "2023-07-01"
37+
}
38+
}
39+
],
40+
"layout": {
41+
"barmode": "overlay",
42+
"title": { "text": "Sampled Results" },
43+
"xaxis": {
44+
"title": { "text": "Date" }
45+
},
46+
"yaxis": { "title": { "text": "Count" } }
47+
}
48+
}

0 commit comments

Comments
 (0)