Skip to content

Commit 12b0f5c

Browse files
committed
in legend implement group titles
1 parent 0ce560c commit 12b0f5c

File tree

9 files changed

+216
-10
lines changed

9 files changed

+216
-10
lines changed

src/components/legend/draw.js

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -393,20 +393,26 @@ function drawTexts(g, gd, legendObj) {
393393
var isEditable = !legendObj._inHover && gd._context.edits.legendText && !isPieLike;
394394
var maxNameLength = legendObj._maxNameLength;
395395

396-
var name;
397-
if(!legendObj.entries) {
398-
name = isPieLike ? legendItem.label : trace.name;
399-
if(trace._meta) {
400-
name = Lib.templateString(name, trace._meta);
401-
}
396+
var name, font;
397+
if(legendItem.groupTitle) {
398+
name = legendItem.groupTitle.text;
399+
font = legendItem.groupTitle.font;
402400
} else {
403-
name = legendItem.text;
401+
font = legendObj.font;
402+
if(!legendObj.entries) {
403+
name = isPieLike ? legendItem.label : trace.name;
404+
if(trace._meta) {
405+
name = Lib.templateString(name, trace._meta);
406+
}
407+
} else {
408+
name = legendItem.text;
409+
}
404410
}
405411

406412
var textEl = Lib.ensureSingle(g, 'text', 'legendtext');
407413

408414
textEl.attr('text-anchor', 'start')
409-
.call(Drawing.font, legendObj.font)
415+
.call(Drawing.font, font)
410416
.text(isEditable ? ensureLength(name, maxNameLength) : name);
411417

412418
var textGap = legendObj.itemwidth + constants.itemGap * 2;
@@ -512,7 +518,15 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
512518
var mathjaxNode = mathjaxGroup.node();
513519
if(!legendObj) legendObj = gd._fullLayout.legend;
514520
var bw = legendObj.borderwidth;
515-
var lineHeight = (aTitle === MAIN_TITLE ? legendObj.title : legendObj).font.size * LINE_SPACING;
521+
var font;
522+
if(aTitle === MAIN_TITLE) {
523+
font = legendObj.title.font;
524+
} else if(legendItem.groupTitle) {
525+
font = legendItem.groupTitle.font;
526+
} else {
527+
font = legendObj.font;
528+
}
529+
var lineHeight = font.size * LINE_SPACING;
516530
var height, width;
517531

518532
if(mathjaxNode) {
@@ -549,8 +563,14 @@ function computeTextDimensions(g, gd, legendObj, aTitle) {
549563
bw + lineHeight
550564
);
551565
} else { // legend item
566+
var x = constants.itemGap * 2 + legendObj.itemwidth;
567+
if(legendItem.groupTitle) {
568+
x = constants.itemGap;
569+
width -= legendObj.itemwidth;
570+
}
571+
552572
svgTextUtils.positionText(textEl,
553-
legendObj.itemwidth + constants.itemGap * 2,
573+
x,
554574
-lineHeight * ((textLines - 1) / 2 - 0.3)
555575
);
556576
}

src/components/legend/get_legend_data.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,28 @@ module.exports = function getLegendData(calcdata, opts) {
119119
legendData[i].sort(orderFn2);
120120
if(reversed) legendData[i].reverse();
121121

122+
var firstItem = legendData[i][0];
123+
124+
var groupTitle = null;
125+
// set group title text
126+
for(j = 0; j < legendData[i].length; j++) {
127+
var gt = legendData[i][j].trace.legendgrouptitle;
128+
if(gt && gt.text) {
129+
groupTitle = gt;
130+
break;
131+
}
132+
}
133+
134+
if(groupTitle) {
135+
legendData[i].unshift({
136+
i: -1,
137+
groupTitle: groupTitle,
138+
trace: {
139+
showlegend: firstItem.trace.showlegend
140+
}
141+
});
142+
}
143+
122144
// rearrange lgroupToTraces into a d3-friendly array of arrays
123145
for(j = 0; j < legendData[i].length; j++) {
124146
legendData[i][j] = [

src/components/legend/handle_click.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ module.exports = function handleClick(g, gd, numClicks) {
3232
[];
3333

3434
var legendItem = g.data()[0][0];
35+
if(legendItem.groupTitle) return; // no click on group legends for now
36+
3537
var fullData = gd._fullData;
3638
var fullTrace = legendItem.trace;
3739
var legendgroup = fullTrace.legendgroup;

src/plots/attributes.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22

3+
var fontAttrs = require('./font_attributes');
34
var fxAttrs = require('../components/fx/attributes');
45

56
module.exports = {
@@ -41,6 +42,23 @@ module.exports = {
4142
'when toggling legend items.'
4243
].join(' ')
4344
},
45+
legendgrouptitle: {
46+
text: {
47+
valType: 'string',
48+
dflt: '',
49+
editType: 'style',
50+
description: [
51+
'Sets the title of the legend group.'
52+
].join(' ')
53+
},
54+
font: fontAttrs({
55+
editType: 'style',
56+
description: [
57+
'Sets this legend group\'s title font.'
58+
].join(' '),
59+
}),
60+
editType: 'style',
61+
},
4462
legendrank: {
4563
valType: 'number',
4664
dflt: 1000,

src/plots/plots.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,13 @@ plots.supplyTraceDefaults = function(traceIn, traceOut, colorIndex, layout, trac
13091309
);
13101310

13111311
coerce('legendgroup');
1312+
var titleText = coerce('legendgrouptitle.text');
1313+
if(titleText) {
1314+
Lib.coerceFont(coerce, 'legendgrouptitle.font', Lib.extendFlat({}, layout.font, {
1315+
size: Math.round(layout.font.size * 1.1) // default to larger font size
1316+
}));
1317+
}
1318+
13121319
coerce('legendrank');
13131320

13141321
traceOut._dfltShowLegend = true;
18.9 KB
Loading
16.4 KB
Loading
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
{
2+
"data": [
3+
{
4+
"type": "pie",
5+
"domain": {
6+
"y": [0.8, 1]
7+
},
8+
"labels": [0],
9+
"legendgroup": "G1"
10+
},
11+
{
12+
"type": "pie",
13+
"domain": {
14+
"y": [0.6, 0.8]
15+
},
16+
"labels": [1],
17+
"legendgroup": "G1"
18+
},
19+
{
20+
"type": "pie",
21+
"domain": {
22+
"y": [0.4, 0.6]
23+
},
24+
"labels": [2],
25+
"legendgroup": "G1",
26+
"legendgrouptitle": {
27+
"text": "First group"
28+
}
29+
},
30+
{
31+
"type": "pie",
32+
"domain": {
33+
"y": [0.2, 0.4]
34+
},
35+
"labels": [3],
36+
"legendgroup": "G2",
37+
"legendgrouptitle": {
38+
"text": "Second group"
39+
}
40+
},
41+
{
42+
"domain": {
43+
"y": [0, 0.2]
44+
},
45+
"type": "pie",
46+
"labels": [4, 5],
47+
"legendgroup": "G3",
48+
"legendgrouptitle": {
49+
"text": "Third group"
50+
}
51+
}
52+
],
53+
"layout": {
54+
"title": {
55+
"text": "legend group titles"
56+
},
57+
"margin": {
58+
"t": 50,
59+
"b": 25,
60+
"l": 25,
61+
"r": 25
62+
},
63+
"width": 300,
64+
"height": 300,
65+
"legend": {
66+
"bgcolor": "lightblue",
67+
"title": {
68+
"text": ""
69+
}
70+
},
71+
"hovermode": "x unified"
72+
}
73+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"data": [
3+
{
4+
"y": [0],
5+
"legendgroup": "G1"
6+
},
7+
{
8+
"y": [1],
9+
"legendgroup": "G1"
10+
},
11+
{
12+
"y": [2],
13+
"legendgroup": "G1",
14+
"legendgrouptitle": {
15+
"text": "First group"
16+
}
17+
},
18+
{
19+
"y": [3],
20+
"legendgroup": "G2",
21+
"legendgrouptitle": {
22+
"text": "Second<br>group",
23+
"font": {
24+
"family": "Raleway",
25+
"size": 14
26+
}
27+
}
28+
},
29+
{
30+
"y": [4],
31+
"legendgroup": "G3",
32+
"legendgrouptitle": {
33+
"text": "Third group"
34+
}
35+
},
36+
{
37+
"y": [5],
38+
"legendgroup": "G3"
39+
}
40+
],
41+
"layout": {
42+
"title": {
43+
"text": "legend group titles"
44+
},
45+
"margin": {
46+
"t": 50,
47+
"b": 25,
48+
"l": 25,
49+
"r": 25
50+
},
51+
"width": 300,
52+
"height": 300,
53+
"yaxis": {
54+
"autorange": "reversed"
55+
},
56+
"legend": {
57+
"bgcolor": "lightblue",
58+
"title": {
59+
"text": ""
60+
}
61+
},
62+
"hovermode": "x unified"
63+
}
64+
}

0 commit comments

Comments
 (0)