Skip to content

Commit 0cfda10

Browse files
committed
implement legend.itemsizing:constant
1 parent a98e0a4 commit 0cfda10

File tree

5 files changed

+247
-26
lines changed

5 files changed

+247
-26
lines changed

src/components/legend/attributes.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ module.exports = {
7878
'Sets the amount of vertical space (in px) between legend groups.'
7979
].join(' ')
8080
},
81+
itemsizing: {
82+
valType: 'enumerated',
83+
values: ['trace', 'constant'],
84+
dflt: 'trace',
85+
role: 'style',
86+
editType: 'legend',
87+
description: [
88+
'Determines if the legend items symbols scale with their corresponding *trace* attributes',
89+
'or remain *constant* independent of the symbol size on the graph.'
90+
].join(' ')
91+
},
92+
8193
x: {
8294
valType: 'number',
8395
min: -2,

src/components/legend/defaults.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
103103
coerce('traceorder', defaultOrder);
104104
if(helpers.isGrouped(layoutOut.legend)) coerce('tracegroupgap');
105105

106+
coerce('itemsizing');
107+
106108
coerce('x', defaultX);
107109
coerce('xanchor', defaultXAnchor);
108110
coerce('y', defaultY);

src/components/legend/style.js

Lines changed: 64 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,38 @@ var Color = require('../color');
1717

1818
var subTypes = require('../../traces/scatter/subtypes');
1919
var stylePie = require('../../traces/pie/style_one');
20+
var pieCastOption = require('../../traces/pie/helpers').castOption;
21+
22+
var CST_MARKER_SIZE = 12;
23+
var CST_LINE_WIDTH = 5;
24+
var CST_MARKER_LINE_WIDTH = 2;
25+
var MAX_LINE_WIDTH = 10;
26+
var MAX_MARKER_LINE_WIDTH = 5;
2027

2128
module.exports = function style(s, gd) {
29+
var fullLayout = gd._fullLayout;
30+
var legend = fullLayout.legend;
31+
var constantItemSizing = legend.itemsizing === 'constant';
32+
33+
function boundLineWidth(mlw, cont, max, cst) {
34+
var v;
35+
if(mlw + 1) {
36+
v = mlw;
37+
} else if(cont && cont.width > 0) {
38+
v = cont.width;
39+
} else {
40+
return 0;
41+
}
42+
return constantItemSizing ? cst : Math.min(v, max);
43+
}
44+
2245
s.each(function(d) {
2346
var traceGroup = d3.select(this);
2447

2548
var layers = Lib.ensureSingle(traceGroup, 'g', 'layers');
2649
layers.style('opacity', d[0].trace.opacity);
2750

28-
// Marker vertical alignment
29-
var valign = gd._fullLayout.legend.valign;
51+
var valign = legend.valign;
3052
var lineHeight = d[0].lineHeight;
3153
var height = d[0].height;
3254

@@ -71,12 +93,14 @@ module.exports = function style(s, gd) {
7193
.each(styleOHLC);
7294

7395
function styleLines(d) {
74-
var trace = d[0].trace;
96+
var d0 = d[0];
97+
var trace = d0.trace;
7598
var showFill = trace.visible && trace.fill && trace.fill !== 'none';
7699
var showLine = subTypes.hasLines(trace);
77100
var contours = trace.contours;
78101
var showGradientLine = false;
79102
var showGradientFill = false;
103+
var dMod, tMod;
80104

81105
if(contours) {
82106
var coloring = contours.coloring;
@@ -113,8 +137,14 @@ module.exports = function style(s, gd) {
113137
fill.attr('d', pathStart + 'h30v6h-30z')
114138
.call(showFill ? Drawing.fillGroupStyle : fillGradient);
115139

140+
if(showLine || showGradientLine) {
141+
var lw = boundLineWidth(undefined, trace.line, MAX_LINE_WIDTH, CST_LINE_WIDTH);
142+
tMod = Lib.minExtend(trace, {line: {width: lw}});
143+
dMod = [Lib.minExtend(d0, {trace: tMod})];
144+
}
145+
116146
var line = this3.select('.legendlines').selectAll('path')
117-
.data(showLine || showGradientLine ? [d] : []);
147+
.data(showLine || showGradientLine ? [dMod] : []);
118148
line.enter().append('path').classed('js-line', true);
119149
line.exit().remove();
120150

@@ -156,12 +186,16 @@ module.exports = function style(s, gd) {
156186
// 'scatter3d' don't use gd.calcdata,
157187
// use d0.trace to infer arrayOk attributes
158188

159-
function boundVal(attrIn, arrayToValFn, bounds) {
189+
function boundVal(attrIn, arrayToValFn, bounds, cst) {
160190
var valIn = Lib.nestedProperty(trace, attrIn).get();
161191
var valToBound = (Lib.isArrayOrTypedArray(valIn) && arrayToValFn) ?
162192
arrayToValFn(valIn) :
163193
valIn;
164194

195+
if(constantItemSizing && valToBound && cst !== undefined) {
196+
valToBound = cst;
197+
}
198+
165199
if(bounds) {
166200
if(valToBound < bounds[0]) return bounds[0];
167201
else if(valToBound > bounds[1]) return bounds[1];
@@ -181,21 +215,21 @@ module.exports = function style(s, gd) {
181215
dEdit.mx = boundVal('marker.symbol', pickFirst);
182216
dEdit.mo = boundVal('marker.opacity', Lib.mean, [0.2, 1]);
183217
dEdit.mlc = boundVal('marker.line.color', pickFirst);
184-
dEdit.mlw = boundVal('marker.line.width', Lib.mean, [0, 5]);
218+
dEdit.mlw = boundVal('marker.line.width', Lib.mean, [0, 5], CST_MARKER_LINE_WIDTH);
185219
tEdit.marker = {
186220
sizeref: 1,
187221
sizemin: 1,
188222
sizemode: 'diameter'
189223
};
190224

191-
var ms = boundVal('marker.size', Lib.mean, [2, 16]);
225+
var ms = boundVal('marker.size', Lib.mean, [2, 16], CST_MARKER_SIZE);
192226
dEdit.ms = ms;
193227
tEdit.marker.size = ms;
194228
}
195229

196230
if(showLines) {
197231
tEdit.line = {
198-
width: boundVal('line.width', pickFirst, [0, 10])
232+
width: boundVal('line.width', pickFirst, [0, 10], CST_LINE_WIDTH)
199233
};
200234
}
201235

@@ -259,12 +293,13 @@ module.exports = function style(s, gd) {
259293
pts.each(function(dd) {
260294
var pt = d3.select(this);
261295
var cont = trace[dd[0]].marker;
296+
var lw = boundLineWidth(undefined, cont.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH);
262297

263298
pt.attr('d', dd[1])
264-
.style('stroke-width', cont.line.width + 'px')
299+
.style('stroke-width', lw + 'px')
265300
.call(Color.fill, cont.color);
266301

267-
if(cont.line.width) {
302+
if(lw) {
268303
pt.call(Color.stroke, cont.line.color);
269304
}
270305
});
@@ -286,7 +321,7 @@ module.exports = function style(s, gd) {
286321
barpath.each(function(d) {
287322
var p = d3.select(this);
288323
var d0 = d[0];
289-
var w = (d0.mlw + 1 || markerLine.width + 1) - 1;
324+
var w = boundLineWidth(d0.mlw, marker.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH);
290325

291326
p.style('stroke-width', w + 'px')
292327
.call(Color.fill, d0.mc || marker.color);
@@ -308,8 +343,8 @@ module.exports = function style(s, gd) {
308343
pts.exit().remove();
309344

310345
pts.each(function() {
311-
var w = trace.line.width;
312346
var p = d3.select(this);
347+
var w = boundLineWidth(undefined, trace.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH);
313348

314349
p.style('stroke-width', w + 'px')
315350
.call(Color.fill, trace.fillcolor);
@@ -334,16 +369,14 @@ module.exports = function style(s, gd) {
334369
pts.exit().remove();
335370

336371
pts.each(function(_, i) {
337-
var container = trace[i ? 'increasing' : 'decreasing'];
338-
var w = container.line.width;
339372
var p = d3.select(this);
373+
var cont = trace[i ? 'increasing' : 'decreasing'];
374+
var w = boundLineWidth(undefined, cont.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH);
340375

341376
p.style('stroke-width', w + 'px')
342-
.call(Color.fill, container.fillcolor);
377+
.call(Color.fill, cont.fillcolor);
343378

344-
if(w) {
345-
Color.stroke(p, container.line.color);
346-
}
379+
if(w) Color.stroke(p, cont.line.color);
347380
});
348381
}
349382

@@ -363,21 +396,20 @@ module.exports = function style(s, gd) {
363396
pts.exit().remove();
364397

365398
pts.each(function(_, i) {
366-
var container = trace[i ? 'increasing' : 'decreasing'];
367-
var w = container.line.width;
368399
var p = d3.select(this);
400+
var cont = trace[i ? 'increasing' : 'decreasing'];
401+
var w = boundLineWidth(undefined, cont.line, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH);
369402

370403
p.style('fill', 'none')
371-
.call(Drawing.dashLine, container.line.dash, w);
404+
.call(Drawing.dashLine, cont.line.dash, w);
372405

373-
if(w) {
374-
Color.stroke(p, container.line.color);
375-
}
406+
if(w) Color.stroke(p, cont.line.color);
376407
});
377408
}
378409

379410
function stylePies(d) {
380-
var trace = d[0].trace;
411+
var d0 = d[0];
412+
var trace = d0.trace;
381413

382414
var pts = d3.select(this).select('g.legendpoints')
383415
.selectAll('path.legendpie')
@@ -387,6 +419,12 @@ module.exports = function style(s, gd) {
387419
.attr('transform', 'translate(20,0)');
388420
pts.exit().remove();
389421

390-
if(pts.size()) pts.call(stylePie, d[0], trace);
422+
if(pts.size()) {
423+
var cont = (trace.marker || {}).line;
424+
var lw = boundLineWidth(pieCastOption(cont.width, d0.pts), cont, MAX_MARKER_LINE_WIDTH, CST_MARKER_LINE_WIDTH);
425+
var tMod = Lib.minExtend(trace, {marker: {line: {width: lw}}});
426+
var d0Mod = Lib.minExtend(d0, {trace: tMod});
427+
stylePie(pts, d0Mod, tMod);
428+
}
391429
}
392430
};
Loading

0 commit comments

Comments
 (0)