Skip to content

Commit

Permalink
Merge pull request #3263 from plotly/2789-valign-legend
Browse files Browse the repository at this point in the history
Legend Marker Vertical Alignment
  • Loading branch information
antoinerg committed Nov 21, 2018
2 parents 695f311 + c1b871d commit 11bec79
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/components/legend/attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,15 @@ module.exports = {
'or *bottom* of the legend.'
].join(' ')
},
editType: 'legend'
editType: 'legend',
valign: {
valType: 'enumerated',
values: ['top', 'middle', 'bottom'],
dflt: 'middle',
role: 'style',
editType: 'legend',
description: [
'Sets the vertical alignment of the symbols with respect to their associated text.',
].join(' ')
}
};
1 change: 1 addition & 0 deletions src/components/legend/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,6 @@ module.exports = function legendDefaults(layoutIn, layoutOut, fullData) {
coerce('xanchor', defaultXAnchor);
coerce('y', defaultY);
coerce('yanchor', defaultYAnchor);
coerce('valign');
Lib.noneOrAll(containerIn, containerOut, ['x', 'y']);
};
1 change: 1 addition & 0 deletions src/components/legend/draw.js
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ function computeTextDimensions(g, gd) {
// to avoid getBoundingClientRect
var textY = lineHeight * (0.3 + (1 - textLines) / 2);
svgTextUtils.positionText(text, constants.textOffsetX, textY);
legendItem.lineHeight = lineHeight;
}

height = Math.max(height, 16) + 3;
Expand Down
13 changes: 13 additions & 0 deletions src/components/legend/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ module.exports = function style(s, gd) {
var layers = Lib.ensureSingle(traceGroup, 'g', 'layers');
layers.style('opacity', d[0].trace.opacity);

// Marker vertical alignment
var valign = gd._fullLayout.legend.valign;
var lineHeight = d[0].lineHeight;
var height = d[0].height;

if(valign === 'middle' || !lineHeight || !height) {
layers.attr('transform', null); // this here is a fun d3 trick to unset DOM attributes
} else {
var factor = {top: 1, bottom: -1}[valign];
var markerOffsetY = factor * (0.5 * (lineHeight - height + 3));
layers.attr('transform', 'translate(0,' + markerOffsetY + ')');
}

var fill = layers
.selectAll('g.legendfill')
.data([d]);
Expand Down
Binary file added test/image/baselines/legend_valign_middle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/image/baselines/legend_valign_top.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions test/image/mocks/legend_valign_middle.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"data": [{
"y": [1, 5, 3, 4, 5],
"name": "Super long name<br>Super long name<br>Super long name<br>Super long name",
"type": "scatter",
"showlegend": true
},
{
"y": [3, 2, 5, 1, 5],
"name": "Also super long name<br>Also super long name<br>Also super long name",
"type": "scatter",
"showlegend": true
}
],
"layout": {
"width": 800,
"legend": {
"bgcolor": "rgba(0,255,255,1)",
"valign": "middle",
"font": {
"size": 20
}
}
}
}
25 changes: 25 additions & 0 deletions test/image/mocks/legend_valign_top.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"data": [{
"y": [1, 5, 3, 4, 5],
"name": "Super long name<br>Super long name<br>Super long name<br>Super long name",
"type": "scatter",
"showlegend": true
},
{
"y": [3, 2, 5, 1, 5],
"name": "Also super long name<br>Also super long name<br>Also super long name",
"type": "scatter",
"showlegend": true
}
],
"layout": {
"width": 800,
"legend": {
"bgcolor": "rgba(0,255,255,1)",
"valign": "top",
"font": {
"size": 20
}
}
}
}
39 changes: 39 additions & 0 deletions test/jasmine/tests/legend_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ var createGraphDiv = require('../assets/create_graph_div');
var destroyGraphDiv = require('../assets/destroy_graph_div');
var assertPlotSize = require('../assets/custom_assertions').assertPlotSize;

var Drawing = require('@src/components/drawing');

describe('legend defaults', function() {
'use strict';

Expand Down Expand Up @@ -665,6 +667,43 @@ describe('legend relayout update', function() {
.catch(failTest)
.then(done);
});

describe('should update legend valign', function() {
var mock = require('@mocks/legend_valign_top.json');
var gd;

beforeEach(function() {
gd = createGraphDiv();
});
afterEach(destroyGraphDiv);

function markerOffsetY() {
var translate = Drawing.getTranslate(d3.select('.legend .traces .layers'));
return translate.y;
}

it('it should translate markers', function(done) {
var mockCopy = Lib.extendDeep({}, mock);

var top, middle, bottom;
Plotly.plot(gd, mockCopy.data, mockCopy.layout)
.then(function() {
top = markerOffsetY();
return Plotly.relayout(gd, 'legend.valign', 'middle');
})
.then(function() {
middle = markerOffsetY();
expect(middle).toBeGreaterThan(top);
return Plotly.relayout(gd, 'legend.valign', 'bottom');
})
.then(function() {
bottom = markerOffsetY();
expect(bottom).toBeGreaterThan(middle);
})
.catch(failTest)
.then(done);
});
});
});

describe('legend orientation change:', function() {
Expand Down

0 comments on commit 11bec79

Please sign in to comment.