Skip to content

Commit 60b0936

Browse files
committed
add legend.itemwidth option to set the width of the symbol area of legends
1 parent 1e17697 commit 60b0936

File tree

8 files changed

+75
-16
lines changed

8 files changed

+75
-16
lines changed

src/components/legend/attributes.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ module.exports = {
9292
'or remain *constant* independent of the symbol size on the graph.'
9393
].join(' ')
9494
},
95+
itemwidth: {
96+
valType: 'number',
97+
dflt: 30,
98+
role: 'style',
99+
editType: 'legend',
100+
description: 'Sets the width (in px) of the legend item symbols (the part other than the text).',
101+
},
95102

96103
itemclick: {
97104
valType: 'enumerated',

src/components/legend/constants.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ module.exports = {
1717

1818
// number of px between legend title and (left) side of legend (always in x direction and from inner border)
1919
titlePad: 2,
20-
// number of px between legend symbol and legend text (always in x direction)
21-
textGap: 40,
2220
// number of px between each legend item (x and/or y direction)
2321
itemGap: 5
2422
};

src/components/legend/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
113113
if(helpers.isGrouped(layoutOut.legend)) coerce('tracegroupgap');
114114

115115
coerce('itemsizing');
116+
coerce('itemwidth');
116117

117118
coerce('itemclick');
118119
coerce('itemdoubleclick');

src/components/legend/draw.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,8 @@ function drawTexts(g, gd, opts) {
412412
.call(Drawing.font, opts.font)
413413
.text(isEditable ? ensureLength(name, maxNameLength) : name);
414414

415-
svgTextUtils.positionText(textEl, constants.textGap, 0);
415+
var textGap = opts.itemwidth + constants.itemGap * 2;
416+
svgTextUtils.positionText(textEl, textGap, 0);
416417

417418
if(isEditable) {
418419
textEl.call(svgTextUtils.makeEditable, {gd: gd, text: name})
@@ -539,7 +540,8 @@ function computeTextDimensions(g, gd, opts) {
539540
// to avoid getBoundingClientRect
540541
var textY = lineHeight * ((textLines - 1) / 2 - 0.3);
541542
if(legendItem) {
542-
svgTextUtils.positionText(textEl, constants.textGap, -textY);
543+
var textGap = opts.itemwidth + constants.itemGap * 2;
544+
svgTextUtils.positionText(textEl, textGap, -textY);
543545
} else { // case of title
544546
svgTextUtils.positionText(textEl, constants.titlePad + bw, lineHeight + bw);
545547
}
@@ -592,8 +594,8 @@ function computeLegendDimensions(gd, groups, traces, opts) {
592594

593595
var bw = opts.borderwidth;
594596
var bw2 = 2 * bw;
595-
var textGap = constants.textGap;
596597
var itemGap = constants.itemGap;
598+
var textGap = opts.itemwidth + itemGap * 2;
597599
var endPad = 2 * (bw + itemGap);
598600

599601
var yanchor = getYanchor(opts);

src/components/legend/style.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ var subTypes = require('../../traces/scatter/subtypes');
2020
var stylePie = require('../../traces/pie/style_one');
2121
var pieCastOption = require('../../traces/pie/helpers').castOption;
2222

23+
var constants = require('./constants');
24+
2325
var CST_MARKER_SIZE = 12;
2426
var CST_LINE_WIDTH = 5;
2527
var CST_MARKER_LINE_WIDTH = 2;
@@ -30,6 +32,8 @@ module.exports = function style(s, gd, legend) {
3032
var fullLayout = gd._fullLayout;
3133
if(!legend) legend = fullLayout.legend;
3234
var constantItemSizing = legend.itemsizing === 'constant';
35+
var itemWidth = legend.itemwidth;
36+
var centerPos = (itemWidth + constants.itemGap * 2) / 2;
3337

3438
var boundLineWidth = function(mlw, cont, max, cst) {
3539
var v;
@@ -161,7 +165,7 @@ module.exports = function style(s, gd, legend) {
161165
.data(showFill || showGradientFill ? [d] : []);
162166
fill.enter().append('path').classed('js-fill', true);
163167
fill.exit().remove();
164-
fill.attr('d', pathStart + 'h30v6h-30z')
168+
fill.attr('d', pathStart + 'h' + itemWidth + 'v6h-' + itemWidth + 'z')
165169
.call(showFill ? Drawing.fillGroupStyle : fillGradient);
166170

167171
if(showLine || showGradientLine) {
@@ -181,7 +185,7 @@ module.exports = function style(s, gd, legend) {
181185
// though there *is* no vertical variation in this case.
182186
// so add an invisibly small angle to the line
183187
// This issue (and workaround) exist across (Mac) Chrome, FF, and Safari
184-
line.attr('d', pathStart + (showGradientLine ? 'l30,0.0001' : 'h30'))
188+
line.attr('d', pathStart + (showGradientLine ? 'l' + itemWidth + ',0.0001' : 'h' + itemWidth))
185189
.call(showLine ? Drawing.lineGroupStyle : lineGradient);
186190
}
187191

@@ -271,7 +275,7 @@ module.exports = function style(s, gd, legend) {
271275
// make sure marker is on the bottom, in case it enters after text
272276
pts.enter().insert('path', ':first-child')
273277
.classed('scatterpts', true)
274-
.attr('transform', 'translate(20,0)');
278+
.attr('transform', 'translate(' + centerPos + ',0)');
275279
pts.exit().remove();
276280
pts.call(Drawing.pointStyle, tMod, gd);
277281

@@ -283,7 +287,7 @@ module.exports = function style(s, gd, legend) {
283287
.data(showText ? dMod : []);
284288
txt.enter()
285289
.append('g').classed('pointtext', true)
286-
.append('text').attr('transform', 'translate(20,0)');
290+
.append('text').attr('transform', 'translate(' + centerPos + ',0)');
287291
txt.exit().remove();
288292
txt.selectAll('text').call(Drawing.textPointStyle, tMod, gd);
289293
}
@@ -311,7 +315,7 @@ module.exports = function style(s, gd, legend) {
311315
.selectAll('path.legendwaterfall')
312316
.data(ptsData);
313317
pts.enter().append('path').classed('legendwaterfall', true)
314-
.attr('transform', 'translate(20,0)')
318+
.attr('transform', 'translate(' + centerPos + ',0)')
315319
.style('stroke-miterlimit', 1);
316320
pts.exit().remove();
317321

@@ -351,7 +355,7 @@ module.exports = function style(s, gd, legend) {
351355
.data(isVisible ? [d] : []);
352356
barpath.enter().append('path').classed('legend' + desiredType, true)
353357
.attr('d', 'M6,6H-6V-6H6Z')
354-
.attr('transform', 'translate(20,0)');
358+
.attr('transform', 'translate(' + centerPos + ',0)');
355359
barpath.exit().remove();
356360

357361
barpath.each(function(d) {
@@ -375,7 +379,7 @@ module.exports = function style(s, gd, legend) {
375379
pts.enter().append('path').classed('legendbox', true)
376380
// if we want the median bar, prepend M6,0H-6
377381
.attr('d', 'M6,6H-6V-6H6Z')
378-
.attr('transform', 'translate(20,0)');
382+
.attr('transform', 'translate(' + centerPos + ',0)');
379383
pts.exit().remove();
380384

381385
pts.each(function() {
@@ -415,7 +419,7 @@ module.exports = function style(s, gd, legend) {
415419
if(i) return 'M-15,0H-8M-8,6V-6H8Z'; // increasing
416420
return 'M15,0H8M8,-6V6H-8Z'; // decreasing
417421
})
418-
.attr('transform', 'translate(20,0)')
422+
.attr('transform', 'translate(' + centerPos + ',0)')
419423
.style('stroke-miterlimit', 1);
420424
pts.exit().remove();
421425

@@ -442,7 +446,7 @@ module.exports = function style(s, gd, legend) {
442446
if(i) return 'M-15,0H0M-8,-6V0'; // increasing
443447
return 'M15,0H0M8,6V0'; // decreasing
444448
})
445-
.attr('transform', 'translate(20,0)')
449+
.attr('transform', 'translate(' + centerPos + ',0)')
446450
.style('stroke-miterlimit', 1);
447451
pts.exit().remove();
448452

@@ -478,7 +482,7 @@ module.exports = function style(s, gd, legend) {
478482
.data(isVisible ? [d] : []);
479483
pts.enter().append('path').classed('legend' + desiredType, true)
480484
.attr('d', 'M6,6H-6V-6H6Z')
481-
.attr('transform', 'translate(20,0)');
485+
.attr('transform', 'translate(' + centerPos + ',0)');
482486
pts.exit().remove();
483487

484488
if(pts.size()) {
@@ -576,7 +580,7 @@ module.exports = function style(s, gd, legend) {
576580
.selectAll('path.legend3dandfriends')
577581
.data(ptsData);
578582
pts.enter().append('path').classed('legend3dandfriends', true)
579-
.attr('transform', 'translate(20,0)')
583+
.attr('transform', 'translate(' + centerPos + ',0)')
580584
.style('stroke-miterlimit', 1);
581585
pts.exit().remove();
582586

27 KB
Loading
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"data": [
3+
{
4+
"x": [
5+
2,
6+
3,
7+
4,
8+
5
9+
],
10+
"y": [
11+
16,
12+
5,
13+
11,
14+
9
15+
],
16+
"line": {
17+
"dash": "dashdot"
18+
},
19+
"type": "scatter"
20+
},
21+
{
22+
"x": [
23+
1,
24+
2,
25+
3,
26+
4
27+
],
28+
"y": [
29+
12,
30+
9,
31+
15,
32+
12
33+
],
34+
"line": {
35+
"dash": "dash"
36+
},
37+
"type": "scatter"
38+
}
39+
],
40+
"layout": {
41+
"legend": {
42+
"itemwidth": 60
43+
}
44+
}
45+
}

test/jasmine/tests/mock_test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ var list = [
669669
'legend_horizontal_one_row',
670670
'legend_horizontal_wrap-alll-lines',
671671
'legend_inside',
672+
'legend_itemwidth_dashline',
672673
'legend_labels',
673674
'legend_large_margin',
674675
'legend_margin-autoexpand-false',
@@ -1733,6 +1734,7 @@ figs['legend_horizontal_groups'] = require('@mocks/legend_horizontal_groups');
17331734
figs['legend_horizontal_one_row'] = require('@mocks/legend_horizontal_one_row');
17341735
figs['legend_horizontal_wrap-alll-lines'] = require('@mocks/legend_horizontal_wrap-alll-lines');
17351736
figs['legend_inside'] = require('@mocks/legend_inside');
1737+
figs['legend_itemwidth_dashline'] = require('@mocks/legend_itemwidth_dashline');
17361738
figs['legend_labels'] = require('@mocks/legend_labels');
17371739
figs['legend_large_margin'] = require('@mocks/legend_large_margin');
17381740
figs['legend_margin-autoexpand-false'] = require('@mocks/legend_margin-autoexpand-false');

0 commit comments

Comments
 (0)