Skip to content

Commit

Permalink
Fixes Issue #3175:
Browse files Browse the repository at this point in the history
- New config parameter options.legend.align, for controlling alignment of legend blocks in horizontal/vertical legends.
- Maintains backward compatibility for legends positioned on the left/right by defaulting to 'start'.
- Replacing nearby pixel unit tests for legend with image based tests
- Documentation for options.legend.align
  • Loading branch information
Dave Kichler committed Mar 18, 2019
1 parent 75e76cf commit c05a2a6
Show file tree
Hide file tree
Showing 19 changed files with 231 additions and 361 deletions.
9 changes: 9 additions & 0 deletions docs/configuration/legend.md
Expand Up @@ -9,6 +9,7 @@ The legend configuration is passed into the `options.legend` namespace. The glob
| ---- | ---- | ------- | -----------
| `display` | `boolean` | `true` | Is the legend shown?
| `position` | `string` | `'top'` | Position of the legend. [more...](#position)
| `align` | `string` | `'center'` | Alignment of the legend. [more...](#align)
| `fullWidth` | `boolean` | `true` | Marks that this box should take the full width of the canvas (pushing down other boxes). This is unlikely to need to be changed in day-to-day use.
| `onClick` | `function` | | A callback that is called when a click event is registered on a label item.
| `onHover` | `function` | | A callback that is called when a 'mousemove' event is registered on top of a label item.
Expand All @@ -23,6 +24,14 @@ Position of the legend. Options are:
* `'bottom'`
* `'right'`

## Align
Alignment of the legend. Options are:
* `'start'` (default for left/right positioned legends)
* `'center'` (default for top/bottom positioned legends)
* `'end'`

Defaults to `'center'` for unrecognized values.

## Legend Label Configuration

The legend label configuration is nested below the legend configuration using the `labels` key.
Expand Down
36 changes: 27 additions & 9 deletions src/plugins/plugin.legend.js
Expand Up @@ -104,6 +104,10 @@ var Legend = Element.extend({
initialize: function(config) {
helpers.extend(this, config);

if (this.options && !this.options.align) {
// to maintain backward compatibility with existing default
this.options.align = this.isHorizontal() ? 'center' : 'start';
}
// Contains hit boxes for each dataset (in dataset order)
this.legendHitBoxes = [];

Expand Down Expand Up @@ -255,7 +259,7 @@ var Legend = Element.extend({

if (i === 0 || lineWidths[lineWidths.length - 1] + width + labelOpts.padding > minSize.width) {
totalHeight += fontSize + labelOpts.padding;
lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = labelOpts.padding;
lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0;
}

// Store the hitbox width and height here. Final position will be updated in `draw`
Expand All @@ -274,6 +278,7 @@ var Legend = Element.extend({
} else {
var vPadding = labelOpts.padding;
var columnWidths = me.columnWidths = [];
var columnHeights = me.columnHeights = [];
var totalWidth = labelOpts.padding;
var currentColWidth = 0;
var currentColHeight = 0;
Expand All @@ -287,7 +292,7 @@ var Legend = Element.extend({
if (i > 0 && currentColHeight + itemHeight > minSize.height - vPadding) {
totalWidth += currentColWidth + labelOpts.padding;
columnWidths.push(currentColWidth); // previous column width

columnHeights.push(currentColHeight);
currentColWidth = 0;
currentColHeight = 0;
}
Expand All @@ -307,6 +312,7 @@ var Legend = Element.extend({

totalWidth += currentColWidth;
columnWidths.push(currentColWidth);
columnHeights.push(currentColHeight);
minSize.width += totalWidth;
}
}
Expand All @@ -329,6 +335,8 @@ var Legend = Element.extend({
var globalDefaults = defaults.global;
var defaultColor = globalDefaults.defaultColor;
var lineDefault = globalDefaults.elements.line;
var legendHeight = me.height;
var columnHeights = me.columnHeights;
var legendWidth = me.width;
var lineWidths = me.lineWidths;

Expand Down Expand Up @@ -408,19 +416,30 @@ var Legend = Element.extend({
}
};

var alignmentOffset = function(dimension, blockSize) {
if (opts.align === 'start') {
return labelOpts.padding;
} else if (opts.align === 'end') {
return dimension - blockSize;
}
// default to center
return (dimension - blockSize + labelOpts.padding) / 2;
};

// Horizontal
var isHorizontal = me.isHorizontal();
var line = 0;
if (isHorizontal) {
cursor = {
x: me.left + ((legendWidth - lineWidths[0]) / 2) + labelOpts.padding,
x: me.left + alignmentOffset(legendWidth, lineWidths[line]),
y: me.top + labelOpts.padding,
line: 0
line: line
};
} else {
cursor = {
x: me.left + labelOpts.padding,
y: me.top + labelOpts.padding,
line: 0
y: me.top + alignmentOffset(legendHeight, columnHeights[line]),
line: line
};
}

Expand All @@ -438,12 +457,12 @@ var Legend = Element.extend({
if (i > 0 && x + width + labelOpts.padding > me.left + me.minSize.width) {
y = cursor.y += itemHeight;
cursor.line++;
x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2) + labelOpts.padding;
x = cursor.x = me.left + alignmentOffset(legendWidth, lineWidths[cursor.line]);
}
} else if (i > 0 && y + itemHeight > me.top + me.minSize.height) {
x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding;
y = cursor.y = me.top + labelOpts.padding;
cursor.line++;
y = cursor.y = me.top + alignmentOffset(legendHeight, columnHeights[cursor.line]);
}

drawLegendBox(x, y, legendItem);
Expand All @@ -459,7 +478,6 @@ var Legend = Element.extend({
} else {
cursor.y += itemHeight;
}

});
}
},
Expand Down
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"],
"datasets": [{
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "left",
"align": "center"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0"],
"datasets": [{
"data": [10]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "left",
"align": "center"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"],
"datasets": [{
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "left",
"align": "end"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"],
"datasets": [{
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "left",
"align": "start"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"],
"datasets": [{
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "top",
"align": "center"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions test/fixtures/plugin.legend/legend-doughnut-top-center-single.json
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0"],
"datasets": [{
"data": [10]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "top",
"align": "center"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"],
"datasets": [{
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "top",
"align": "end"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -0,0 +1,24 @@
{
"config": {
"type": "doughnut",
"data": {
"labels": ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16"],
"datasets": [{
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30]
}]
},
"options": {
"responsive": false,
"legend": {
"position": "top",
"align": "start"
}
}
},
"options": {
"canvas": {
"height": 256,
"width": 512
}
}
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c05a2a6

Please sign in to comment.