Skip to content

Commit 75efb31

Browse files
committed
fix #4132 - fix horizontal legend dimension computations
- which gives better margin pushes, fixes legendgroup_horizontal_wrapping mock - use per-item width for toggle-rect width in ALL horizontal legends, we could eventually compute "per-column" width, if someone finds it useful
1 parent 022b2ac commit 75efb31

File tree

6 files changed

+37
-47
lines changed

6 files changed

+37
-47
lines changed

src/components/legend/draw.js

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -540,64 +540,55 @@ function computeLegendDimensions(gd, groups, traces) {
540540
combinedItemWidth += w;
541541
});
542542

543+
toggleRectWidth = null;
544+
var maxRowWidth = 0;
545+
543546
if(isGrouped) {
544-
var groupData = groups.data();
545-
var i;
547+
var maxGroupHeightInRow = 0;
548+
var groupOffsetX = 0;
549+
var groupOffsetY = 0;
550+
groups.each(function() {
551+
var maxWidthInGroup = 0;
552+
var offsetY = 0;
553+
d3.select(this).selectAll('g.traces').each(function(d) {
554+
var h = d[0].height;
555+
Drawing.setTranslate(this, 0, itemGap + bw + h / 2 + offsetY);
556+
offsetY += h;
557+
maxWidthInGroup = Math.max(maxWidthInGroup, textGap + d[0].width);
558+
});
559+
maxGroupHeightInRow = Math.max(maxGroupHeightInRow, offsetY);
546560

547-
var maxGroupHeight = 0;
548-
for(i = 0; i < groupData.length; i++) {
549-
var groupHeight = groupData[i].reduce(function(a, b) { return a + b[0].height; }, 0);
550-
maxGroupHeight = Math.max(maxGroupHeight, groupHeight);
551-
}
561+
var next = maxWidthInGroup + itemGap;
552562

553-
var groupXOffsets = [opts._width];
554-
var groupYOffsets = [];
555-
var rowNum = 0;
556-
for(i = 0; i < groupData.length; i++) {
557-
if((opts._width + itemGap + maxItemWidth + bw) > opts._maxWidth) {
558-
groupXOffsets[groupXOffsets.length - 1] = groupXOffsets[0];
559-
opts._width = maxItemWidth + itemGap;
560-
rowNum++;
561-
} else {
562-
opts._width += maxItemWidth + itemGap;
563+
if((next + bw + groupOffsetX) > opts._maxWidth) {
564+
maxRowWidth = Math.max(maxRowWidth, groupOffsetX);
565+
groupOffsetX = 0;
566+
groupOffsetY += maxGroupHeightInRow + opts.tracegroupgap;
567+
maxGroupHeightInRow = offsetY;
563568
}
564569

565-
groupXOffsets.push(opts._width);
566-
groupYOffsets.push(rowNum * maxGroupHeight + (rowNum > 0 ? opts.tracegroupgap : 0));
567-
}
568-
569-
groups.each(function(d, i) {
570-
Drawing.setTranslate(this, groupXOffsets[i], groupYOffsets[i]);
571-
});
570+
Drawing.setTranslate(this, groupOffsetX, groupOffsetY);
572571

573-
groups.each(function() {
574-
var group = d3.select(this);
575-
var groupTraces = group.selectAll('g.traces');
576-
var groupHeight = 0;
577-
578-
groupTraces.each(function(d) {
579-
var h = d[0].height;
580-
Drawing.setTranslate(this, 0, itemGap + bw + groupHeight + h / 2);
581-
groupHeight += h;
582-
});
572+
groupOffsetX += next;
583573
});
584574

585-
opts._height = groupYOffsets[groupYOffsets.length - 1] + maxGroupHeight + endPad;
586-
opts._width = Math.max.apply(null, groupXOffsets) + maxItemWidth + textGap + bw2;
587-
toggleRectWidth = maxItemWidth;
575+
opts._width = Math.max(maxRowWidth, groupOffsetX) + bw;
576+
opts._height = groupOffsetY + maxGroupHeightInRow + endPad;
588577
} else {
589-
var oneRowLegend = (combinedItemWidth + bw2 + (traces.size() - 1) * itemGap) < opts._maxWidth;
578+
var nTraces = traces.size();
579+
var oneRowLegend = (combinedItemWidth + bw2 + (nTraces - 1) * itemGap) < opts._maxWidth;
590580

591-
var maxRowWidth = 0;
592581
var maxItemHeightInRow = 0;
593582
var offsetX = 0;
594583
var offsetY = 0;
584+
var rowWidth = 0;
595585
traces.each(function(d) {
596586
var h = d[0].height;
597-
var next = (oneRowLegend ? textGap + d[0].width : maxItemWidth) + itemGap;
587+
var w = textGap + d[0].width;
588+
var next = (oneRowLegend ? w : maxItemWidth) + itemGap;
598589

599590
if((next + bw + offsetX) > opts._maxWidth) {
600-
maxRowWidth = Math.max(maxRowWidth, offsetX);
591+
maxRowWidth = Math.max(maxRowWidth, rowWidth);
601592
offsetX = 0;
602593
offsetY += maxItemHeightInRow;
603594
opts._height += maxItemHeightInRow;
@@ -606,18 +597,17 @@ function computeLegendDimensions(gd, groups, traces) {
606597

607598
Drawing.setTranslate(this, bw + offsetX, itemGap + bw + h / 2 + offsetY);
608599

600+
rowWidth = offsetX + w + itemGap;
609601
offsetX += next;
610602
maxItemHeightInRow = Math.max(maxItemHeightInRow, h);
611603
});
612604

613605
if(oneRowLegend) {
614606
opts._width = offsetX + bw2;
615607
opts._height = maxItemHeightInRow + endPad;
616-
toggleRectWidth = null;
617608
} else {
618-
opts._width = Math.max(maxRowWidth, offsetX) + bw;
609+
opts._width = Math.max(maxRowWidth, rowWidth) + bw2;
619610
opts._height += maxItemHeightInRow + endPad;
620-
toggleRectWidth = maxItemWidth;
621611
}
622612
}
623613
}
-31 Bytes
Loading
-34 Bytes
Loading
Loading
Loading

test/jasmine/tests/legend_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -719,15 +719,15 @@ describe('legend relayout update', function() {
719719
var mockCopy = Lib.extendDeep({}, mock);
720720
Plotly.newPlot(gd, mockCopy)
721721
.then(function() {
722-
expect(gd._fullLayout._size.b).toBe(130);
722+
expect(gd._fullLayout._size.b).toBe(113);
723723
return Plotly.relayout(gd, 'legend.tracegroupgap', 70);
724724
})
725725
.then(function() {
726-
expect(gd._fullLayout._size.b).toBe(185);
726+
expect(gd._fullLayout._size.b).toBe(167);
727727
return Plotly.relayout(gd, 'legend.tracegroupgap', 10);
728728
})
729729
.then(function() {
730-
expect(gd._fullLayout._size.b).toBe(130);
730+
expect(gd._fullLayout._size.b).toBe(113);
731731
})
732732
.catch(failTest)
733733
.then(done);

0 commit comments

Comments
 (0)