Implement legend.align: 'start', 'center', 'end' (#6141)
New `options.legend.align`config option for controlling alignment of legend blocks in horizontal/vertical legends.
@ -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.
|
||||
@ -23,6 +24,14 @@ Position of the legend. Options are:
|
||||
* `'bottom'`
|
||||
* `'right'`
|
||||
|
||||
## Align
|
||||
Alignment of the legend. Options are:
|
||||
* `'start'`
|
||||
* `'center'`
|
||||
* `'end'`
|
||||
|
||||
Defaults to `'center'` for unrecognized values.
|
||||
|
||||
## Legend Label Configuration
|
||||
|
||||
The legend label configuration is nested below the legend configuration using the `labels` key.
|
||||
|
||||
@ -12,6 +12,7 @@ defaults._set('global', {
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top',
|
||||
align: 'center',
|
||||
fullWidth: true,
|
||||
reverse: false,
|
||||
weight: 1000,
|
||||
@ -102,18 +103,19 @@ function getBoxWidth(labelOpts, fontSize) {
|
||||
var Legend = Element.extend({
|
||||
|
||||
initialize: function(config) {
|
||||
helpers.extend(this, config);
|
||||
var me = this;
|
||||
helpers.extend(me, config);
|
||||
|
||||
// Contains hit boxes for each dataset (in dataset order)
|
||||
this.legendHitBoxes = [];
|
||||
me.legendHitBoxes = [];
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this._hoveredItem = null;
|
||||
me._hoveredItem = null;
|
||||
|
||||
// Are we in doughnut mode which has a different data type
|
||||
this.doughnutMode = false;
|
||||
me.doughnutMode = false;
|
||||
},
|
||||
|
||||
// These methods are ordered by lifecycle. Utilities then follow.
|
||||
@ -253,9 +255,9 @@ var Legend = Element.extend({
|
||||
var boxWidth = getBoxWidth(labelOpts, fontSize);
|
||||
var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
|
||||
|
||||
if (i === 0 || lineWidths[lineWidths.length - 1] + width + labelOpts.padding > minSize.width) {
|
||||
if (i === 0 || lineWidths[lineWidths.length - 1] + width + 2 * 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`
|
||||
@ -274,27 +276,27 @@ 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;
|
||||
var itemHeight = fontSize + vPadding;
|
||||
|
||||
helpers.each(me.legendItems, function(legendItem, i) {
|
||||
var boxWidth = getBoxWidth(labelOpts, fontSize);
|
||||
var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
|
||||
|
||||
// If too tall, go to new column
|
||||
if (i > 0 && currentColHeight + itemHeight > minSize.height - vPadding) {
|
||||
if (i > 0 && currentColHeight + fontSize + 2 * vPadding > minSize.height) {
|
||||
totalWidth += currentColWidth + labelOpts.padding;
|
||||
columnWidths.push(currentColWidth); // previous column width
|
||||
|
||||
columnHeights.push(currentColHeight);
|
||||
currentColWidth = 0;
|
||||
currentColHeight = 0;
|
||||
}
|
||||
|
||||
// Get max width
|
||||
currentColWidth = Math.max(currentColWidth, itemWidth);
|
||||
currentColHeight += itemHeight;
|
||||
currentColHeight += fontSize + vPadding;
|
||||
|
||||
// Store the hitbox width and height here. Final position will be updated in `draw`
|
||||
hitboxes[i] = {
|
||||
@ -307,6 +309,7 @@ var Legend = Element.extend({
|
||||
|
||||
totalWidth += currentColWidth;
|
||||
columnWidths.push(currentColWidth);
|
||||
columnHeights.push(currentColHeight);
|
||||
minSize.width += totalWidth;
|
||||
}
|
||||
}
|
||||
@ -329,6 +332,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;
|
||||
|
||||
@ -408,18 +413,29 @@ var Legend = Element.extend({
|
||||
}
|
||||
};
|
||||
|
||||
var alignmentOffset = function(dimension, blockSize) {
|
||||
switch (opts.align) {
|
||||
case 'start':
|
||||
return labelOpts.padding;
|
||||
case 'end':
|
||||
return dimension - blockSize;
|
||||
default: // center
|
||||
return (dimension - blockSize + labelOpts.padding) / 2;
|
||||
}
|
||||
};
|
||||
|
||||
// Horizontal
|
||||
var isHorizontal = me.isHorizontal();
|
||||
if (isHorizontal) {
|
||||
cursor = {
|
||||
x: me.left + ((legendWidth - lineWidths[0]) / 2) + labelOpts.padding,
|
||||
x: me.left + alignmentOffset(legendWidth, lineWidths[0]),
|
||||
y: me.top + labelOpts.padding,
|
||||
line: 0
|
||||
};
|
||||
} else {
|
||||
cursor = {
|
||||
x: me.left + labelOpts.padding,
|
||||
y: me.top + labelOpts.padding,
|
||||
y: me.top + alignmentOffset(legendHeight, columnHeights[0]),
|
||||
line: 0
|
||||
};
|
||||
}
|
||||
@ -438,12 +454,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);
|
||||
@ -459,7 +475,6 @@ var Legend = Element.extend({
|
||||
} else {
|
||||
cursor.y += itemHeight;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
25
test/fixtures/plugin.legend/legend-doughnut-bottom-center-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 20, 10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "bottom",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-bottom-center-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-bottom-center-single.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": [""],
|
||||
"datasets": [{
|
||||
"data": [10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "bottom",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-bottom-center-single.png
vendored
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-bottom-end-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "bottom",
|
||||
"align": "end"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-bottom-end-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-bottom-start-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "bottom",
|
||||
"align": "start"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-bottom-start-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-left-center-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "left",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-left-center-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-left-center-single.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": [""],
|
||||
"datasets": [{
|
||||
"data": [10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "left",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-left-center-single.png
vendored
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
24
test/fixtures/plugin.legend/legend-doughnut-left-default-center.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "left"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-left-default-center.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-left-end-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "left",
|
||||
"align": "end"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-left-end-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-left-start-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "left",
|
||||
"align": "start"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-left-start-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-right-center-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "right",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-right-center-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-right-center-single.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": [""],
|
||||
"datasets": [{
|
||||
"data": [10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "right",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-right-center-single.png
vendored
Normal file
|
After Width: | Height: | Size: 10 KiB |
24
test/fixtures/plugin.legend/legend-doughnut-right-default-center.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "right"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-right-default-center.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-right-end-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "right",
|
||||
"align": "end"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-right-end-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-right-start-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "right",
|
||||
"align": "start"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-right-start-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-top-center-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 20, 10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "top",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-top-center-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 12 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-top-center-single.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": [""],
|
||||
"datasets": [{
|
||||
"data": [10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "top",
|
||||
"align": "center"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-top-center-single.png
vendored
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-top-end-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "top",
|
||||
"align": "end"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-top-end-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
25
test/fixtures/plugin.legend/legend-doughnut-top-start-mulitiline.json
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"config": {
|
||||
"type": "doughnut",
|
||||
"data": {
|
||||
"labels": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""],
|
||||
"datasets": [{
|
||||
"data": [10, 20, 30, 40, 50, 60, 70, 10, 20, 30, 40, 50, 60, 70, 10],
|
||||
"backgroundColor": "#00ff00",
|
||||
"borderWidth": 0
|
||||
}]
|
||||
},
|
||||
"options": {
|
||||
"legend": {
|
||||
"position": "top",
|
||||
"align": "start"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"canvas": {
|
||||
"height": 256,
|
||||
"width": 512
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
test/fixtures/plugin.legend/legend-doughnut-top-start-mulitiline.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
@ -1,9 +1,12 @@
|
||||
// Test the rectangle element
|
||||
describe('Legend block tests', function() {
|
||||
describe('auto', jasmine.fixture.specs('plugin.legend'));
|
||||
|
||||
it('should have the correct default config', function() {
|
||||
expect(Chart.defaults.global.legend).toEqual({
|
||||
display: true,
|
||||
position: 'top',
|
||||
align: 'center',
|
||||
fullWidth: true, // marks that this box should take the full width of the canvas (pushing down other boxes)
|
||||
reverse: false,
|
||||
weight: 1000,
|
||||
@ -177,358 +180,6 @@ describe('Legend block tests', function() {
|
||||
expect(makeChart).not.toThrow();
|
||||
});
|
||||
|
||||
it('should draw correctly when the legend is positioned on the top', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'dataset1',
|
||||
backgroundColor: '#f31',
|
||||
borderCapStyle: 'butt',
|
||||
borderDash: [2, 2],
|
||||
borderDashOffset: 5.5,
|
||||
data: []
|
||||
}, {
|
||||
label: 'dataset2',
|
||||
hidden: true,
|
||||
borderJoinStyle: 'miter',
|
||||
data: []
|
||||
}, {
|
||||
label: 'dataset3',
|
||||
borderWidth: 10,
|
||||
borderColor: 'green',
|
||||
data: []
|
||||
}],
|
||||
labels: []
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.legend.legendHitBoxes.length).toBe(3);
|
||||
|
||||
[
|
||||
{h: 12, l: 106, t: 10, w: 93},
|
||||
{h: 12, l: 209, t: 10, w: 93},
|
||||
{h: 12, l: 312, t: 10, w: 93}
|
||||
].forEach(function(expected, i) {
|
||||
expect(chart.legend.legendHitBoxes[i].height).toBeCloseToPixel(expected.h);
|
||||
expect(chart.legend.legendHitBoxes[i].left).toBeCloseToPixel(expected.l);
|
||||
expect(chart.legend.legendHitBoxes[i].top).toBeCloseToPixel(expected.t);
|
||||
expect(chart.legend.legendHitBoxes[i].width).toBeCloseToPixel(expected.w);
|
||||
});
|
||||
|
||||
// NOTE(SB) We should get ride of the following tests and use image diff instead.
|
||||
// For now, as discussed with Evert Timberg, simply comment out.
|
||||
// See https://humblesoftware.github.io/js-imagediff/test.html
|
||||
/* chart.legend.ctx = window.createMockContext();
|
||||
chart.update();
|
||||
|
||||
expect(chart.legend.ctx .getCalls()).toEqual([{
|
||||
"name": "measureText",
|
||||
"args": ["dataset1"]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset2"]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset3"]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset1"]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset2"]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset3"]
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [0.5]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["#666"]
|
||||
}, {
|
||||
"name": "setFillStyle",
|
||||
"args": ["#666"]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset1"]
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "setFillStyle",
|
||||
"args": ["#f31"]
|
||||
}, {
|
||||
"name": "setLineCap",
|
||||
"args": ["butt"]
|
||||
}, {
|
||||
"name": "setLineDashOffset",
|
||||
"args": [5.5]
|
||||
}, {
|
||||
"name": "setLineJoin",
|
||||
"args": ["miter"]
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [3]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["rgba(0,0,0,0.1)"]
|
||||
}, {
|
||||
"name": "setLineDash",
|
||||
"args": [
|
||||
[2, 2]
|
||||
]
|
||||
}, {
|
||||
"name": "strokeRect",
|
||||
"args": [114, 110, 40, 12]
|
||||
}, {
|
||||
"name": "fillRect",
|
||||
"args": [114, 110, 40, 12]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["dataset1", 160, 110]
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset2"]
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "setFillStyle",
|
||||
"args": ["rgba(0,0,0,0.1)"]
|
||||
}, {
|
||||
"name": "setLineCap",
|
||||
"args": ["butt"]
|
||||
}, {
|
||||
"name": "setLineDashOffset",
|
||||
"args": [0]
|
||||
}, {
|
||||
"name": "setLineJoin",
|
||||
"args": ["miter"]
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [3]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["rgba(0,0,0,0.1)"]
|
||||
}, {
|
||||
"name": "setLineDash",
|
||||
"args": [
|
||||
[]
|
||||
]
|
||||
}, {
|
||||
"name": "strokeRect",
|
||||
"args": [250, 110, 40, 12]
|
||||
}, {
|
||||
"name": "fillRect",
|
||||
"args": [250, 110, 40, 12]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["dataset2", 296, 110]
|
||||
}, {
|
||||
"name": "beginPath",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [2]
|
||||
}, {
|
||||
"name": "moveTo",
|
||||
"args": [296, 116]
|
||||
}, {
|
||||
"name": "lineTo",
|
||||
"args": [376, 116]
|
||||
}, {
|
||||
"name": "stroke",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "measureText",
|
||||
"args": ["dataset3"]
|
||||
}, {
|
||||
"name": "save",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "setFillStyle",
|
||||
"args": ["rgba(0,0,0,0.1)"]
|
||||
}, {
|
||||
"name": "setLineCap",
|
||||
"args": ["butt"]
|
||||
}, {
|
||||
"name": "setLineDashOffset",
|
||||
"args": [0]
|
||||
}, {
|
||||
"name": "setLineJoin",
|
||||
"args": ["miter"]
|
||||
}, {
|
||||
"name": "setLineWidth",
|
||||
"args": [10]
|
||||
}, {
|
||||
"name": "setStrokeStyle",
|
||||
"args": ["green"]
|
||||
}, {
|
||||
"name": "setLineDash",
|
||||
"args": [
|
||||
[]
|
||||
]
|
||||
}, {
|
||||
"name": "strokeRect",
|
||||
"args": [182, 132, 40, 12]
|
||||
}, {
|
||||
"name": "fillRect",
|
||||
"args": [182, 132, 40, 12]
|
||||
}, {
|
||||
"name": "restore",
|
||||
"args": []
|
||||
}, {
|
||||
"name": "fillText",
|
||||
"args": ["dataset3", 228, 132]
|
||||
}]);*/
|
||||
});
|
||||
|
||||
it('should draw correctly when the legend is positioned on the left', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'dataset1',
|
||||
backgroundColor: '#f31',
|
||||
borderCapStyle: 'butt',
|
||||
borderDash: [2, 2],
|
||||
borderDashOffset: 5.5,
|
||||
data: []
|
||||
}, {
|
||||
label: 'dataset2',
|
||||
hidden: true,
|
||||
borderJoinStyle: 'miter',
|
||||
data: []
|
||||
}, {
|
||||
label: 'dataset3',
|
||||
borderWidth: 10,
|
||||
borderColor: 'green',
|
||||
data: []
|
||||
}],
|
||||
labels: []
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
position: 'left'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.legend.legendHitBoxes.length).toBe(3);
|
||||
|
||||
[
|
||||
{h: 12, l: 10, t: 16, w: 93},
|
||||
{h: 12, l: 10, t: 38, w: 93},
|
||||
{h: 12, l: 10, t: 60, w: 93}
|
||||
].forEach(function(expected, i) {
|
||||
expect(chart.legend.legendHitBoxes[i].height).toBeCloseToPixel(expected.h);
|
||||
expect(chart.legend.legendHitBoxes[i].left).toBeCloseToPixel(expected.l);
|
||||
expect(chart.legend.legendHitBoxes[i].top).toBeCloseToPixel(expected.t);
|
||||
expect(chart.legend.legendHitBoxes[i].width).toBeCloseToPixel(expected.w);
|
||||
});
|
||||
});
|
||||
|
||||
it('should draw correctly when the legend is positioned on the top and has multiple rows', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: Array.apply(null, Array(9)).map(function() {
|
||||
return {
|
||||
label: ' ',
|
||||
data: []
|
||||
};
|
||||
}),
|
||||
labels: []
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.legend.left).toBeCloseToPixel(0);
|
||||
expect(chart.legend.top).toBeCloseToPixel(0);
|
||||
expect(chart.legend.width).toBeCloseToPixel(512);
|
||||
expect(chart.legend.height).toBeCloseToPixel(54);
|
||||
expect(chart.legend.legendHitBoxes.length).toBe(9);
|
||||
|
||||
[
|
||||
{h: 12, l: 24, t: 10, w: 49},
|
||||
{h: 12, l: 83, t: 10, w: 49},
|
||||
{h: 12, l: 142, t: 10, w: 49},
|
||||
{h: 12, l: 202, t: 10, w: 49},
|
||||
{h: 12, l: 261, t: 10, w: 49},
|
||||
{h: 12, l: 320, t: 10, w: 49},
|
||||
{h: 12, l: 380, t: 10, w: 49},
|
||||
{h: 12, l: 439, t: 10, w: 49},
|
||||
{h: 12, l: 231, t: 32, w: 49}
|
||||
].forEach(function(expected, i) {
|
||||
expect(chart.legend.legendHitBoxes[i].height).toBeCloseToPixel(expected.h);
|
||||
expect(chart.legend.legendHitBoxes[i].left).toBeCloseToPixel(expected.l);
|
||||
expect(chart.legend.legendHitBoxes[i].top).toBeCloseToPixel(expected.t);
|
||||
expect(chart.legend.legendHitBoxes[i].width).toBeCloseToPixel(expected.w);
|
||||
});
|
||||
});
|
||||
|
||||
it('should draw correctly when the legend is positioned on the left and has multiple columns', function() {
|
||||
var chart = window.acquireChart({
|
||||
type: 'bar',
|
||||
data: {
|
||||
datasets: Array.apply(null, Array(22)).map(function() {
|
||||
return {
|
||||
label: ' ',
|
||||
data: []
|
||||
};
|
||||
}),
|
||||
labels: []
|
||||
},
|
||||
options: {
|
||||
legend: {
|
||||
position: 'left'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(chart.legend.left).toBeCloseToPixel(0);
|
||||
expect(chart.legend.top).toBeCloseToPixel(6);
|
||||
expect(chart.legend.width).toBeCloseToPixel(128);
|
||||
expect(chart.legend.height).toBeCloseToPixel(476);
|
||||
expect(chart.legend.legendHitBoxes.length).toBe(22);
|
||||
|
||||
[
|
||||
{h: 12, l: 10, t: 16, w: 49},
|
||||
{h: 12, l: 10, t: 38, w: 49},
|
||||
{h: 12, l: 10, t: 60, w: 49},
|
||||
{h: 12, l: 10, t: 82, w: 49},
|
||||
{h: 12, l: 10, t: 104, w: 49},
|
||||
{h: 12, l: 10, t: 126, w: 49},
|
||||
{h: 12, l: 10, t: 148, w: 49},
|
||||
{h: 12, l: 10, t: 170, w: 49},
|
||||
{h: 12, l: 10, t: 192, w: 49},
|
||||
{h: 12, l: 10, t: 214, w: 49},
|
||||
{h: 12, l: 10, t: 236, w: 49},
|
||||
{h: 12, l: 10, t: 258, w: 49},
|
||||
{h: 12, l: 10, t: 280, w: 49},
|
||||
{h: 12, l: 10, t: 302, w: 49},
|
||||
{h: 12, l: 10, t: 324, w: 49},
|
||||
{h: 12, l: 10, t: 346, w: 49},
|
||||
{h: 12, l: 10, t: 368, w: 49},
|
||||
{h: 12, l: 10, t: 390, w: 49},
|
||||
{h: 12, l: 10, t: 412, w: 49},
|
||||
{h: 12, l: 10, t: 434, w: 49},
|
||||
{h: 12, l: 10, t: 456, w: 49},
|
||||
{h: 12, l: 69, t: 16, w: 49}
|
||||
].forEach(function(expected, i) {
|
||||
expect(chart.legend.legendHitBoxes[i].height).toBeCloseToPixel(expected.h);
|
||||
expect(chart.legend.legendHitBoxes[i].left).toBeCloseToPixel(expected.l);
|
||||
expect(chart.legend.legendHitBoxes[i].top).toBeCloseToPixel(expected.t);
|
||||
expect(chart.legend.legendHitBoxes[i].width).toBeCloseToPixel(expected.w);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not draw legend items outside of the chart bounds', function() {
|
||||
var chart = window.acquireChart(
|
||||
{
|
||||
@ -704,3 +355,4 @@ describe('Legend block tests', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||