Skip to content

Commit

Permalink
Enable custom legend box heights (#7459)
Browse files Browse the repository at this point in the history
Enable custom legend box heights
  • Loading branch information
etimberg authored Jun 4, 2020
1 parent 690d07b commit 0703d78
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 14 deletions.
1 change: 1 addition & 0 deletions docs/docs/configuration/legend.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ The legend label configuration is nested below the legend configuration using th
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| `boxWidth` | `number` | `40` | Width of coloured box.
| `boxHeight` | `number` | fontSize | Height of the coloured box.
| `font` | `Font` | `defaults.font` | See [Fonts](fonts.md)
| `padding` | `number` | `10` | Padding between rows of colored boxes.
| `generateLabels` | `function` | | Generates legend items for each thing in the legend. Default implementation returns the text + styling for the color box. See [Legend Item](#legend-item-interface) for details.
Expand Down
47 changes: 33 additions & 14 deletions src/plugins/plugin.legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import defaults from '../core/core.defaults';
import Element from '../core/core.element';
import layouts from '../core/core.layouts';
import {drawPoint} from '../helpers/helpers.canvas';
import {callback as call, mergeIf, valueOrDefault} from '../helpers/helpers.core';
import {callback as call, mergeIf, valueOrDefault, isNullOrUndef} from '../helpers/helpers.core';
import {toFont, toPadding} from '../helpers/helpers.options';
import {getRtlAdapter, overrideTextDirection, restoreTextDirection} from '../helpers/helpers.rtl';

Expand Down Expand Up @@ -90,9 +90,23 @@ defaults.set('legend', {
* @return {number} width of the color box area
*/
function getBoxWidth(labelOpts, fontSize) {
return labelOpts.usePointStyle && labelOpts.boxWidth > fontSize ?
const {boxWidth} = labelOpts;
return (labelOpts.usePointStyle && boxWidth > fontSize) || isNullOrUndef(boxWidth) ?
fontSize :
labelOpts.boxWidth;
boxWidth;
}

/**
* Helper function to get the box height
* @param {object} labelOpts - the label options on the legend
* @param {*} fontSize - the label font size
* @return {number} height of the color box area
*/
function getBoxHeight(labelOpts, fontSize) {
const {boxHeight} = labelOpts;
return (labelOpts.usePointStyle && boxHeight > fontSize) || isNullOrUndef(boxHeight) ?
fontSize :
boxHeight;
}

export class Legend extends Element {
Expand Down Expand Up @@ -239,6 +253,9 @@ export class Legend extends Element {
const ctx = me.ctx;
const labelFont = toFont(labelOpts.font);
const fontSize = labelFont.size;
const boxWidth = getBoxWidth(labelOpts, fontSize);
const boxHeight = getBoxHeight(labelOpts, fontSize);
const itemHeight = Math.max(boxHeight, fontSize);

// Reset hit boxes
const hitboxes = me.legendHitBoxes = [];
Expand Down Expand Up @@ -271,11 +288,10 @@ export class Legend extends Element {
ctx.textBaseline = 'middle';

me.legendItems.forEach((legendItem, i) => {
const boxWidth = getBoxWidth(labelOpts, fontSize);
const width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;

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

Expand All @@ -284,7 +300,7 @@ export class Legend extends Element {
left: 0,
top: 0,
width,
height: fontSize
height: itemHeight
};

lineWidths[lineWidths.length - 1] += width + labelOpts.padding;
Expand All @@ -302,7 +318,6 @@ export class Legend extends Element {

const heightLimit = minSize.height - titleHeight;
me.legendItems.forEach((legendItem, i) => {
const boxWidth = getBoxWidth(labelOpts, fontSize);
const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;

// If too tall, go to new column
Expand All @@ -323,7 +338,7 @@ export class Legend extends Element {
left: 0,
top: 0,
width: itemWidth,
height: fontSize
height: itemHeight,
};
});

Expand Down Expand Up @@ -377,11 +392,13 @@ export class Legend extends Element {
ctx.font = labelFont.string;

const boxWidth = getBoxWidth(labelOpts, fontSize);
const boxHeight = getBoxHeight(labelOpts, fontSize);
const height = Math.max(fontSize, boxHeight);
const hitboxes = me.legendHitBoxes;

// current position
const drawLegendBox = function(x, y, legendItem) {
if (isNaN(boxWidth) || boxWidth <= 0) {
if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {
return;
}

Expand Down Expand Up @@ -417,9 +434,12 @@ export class Legend extends Element {
drawPoint(ctx, drawOptions, centerX, centerY);
} else {
// Draw box as legend symbol
ctx.fillRect(rtlHelper.leftForLtr(x, boxWidth), y, boxWidth, fontSize);
// Adjust position when boxHeight < fontSize (want it centered)
const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);

ctx.fillRect(rtlHelper.leftForLtr(x, boxWidth), yBoxTop, boxWidth, boxHeight);
if (lineWidth !== 0) {
ctx.strokeRect(rtlHelper.leftForLtr(x, boxWidth), y, boxWidth, fontSize);
ctx.strokeRect(rtlHelper.leftForLtr(x, boxWidth), yBoxTop, boxWidth, boxHeight);
}
}

Expand All @@ -429,8 +449,7 @@ export class Legend extends Element {
const fillText = function(x, y, legendItem, textWidth) {
const halfFontSize = fontSize / 2;
const xLeft = rtlHelper.xPlus(x, boxWidth + halfFontSize);
const yMiddle = y + halfFontSize;

const yMiddle = y + (height / 2);
ctx.fillText(legendItem.text, xLeft, yMiddle);

if (legendItem.hidden) {
Expand Down Expand Up @@ -473,7 +492,7 @@ export class Legend extends Element {

overrideTextDirection(me.ctx, opts.textDirection);

const itemHeight = fontSize + labelOpts.padding;
const itemHeight = height + labelOpts.padding;
me.legendItems.forEach((legendItem, i) => {
const textWidth = ctx.measureText(legendItem.text).width;
const width = boxWidth + (fontSize / 2) + textWidth;
Expand Down
31 changes: 31 additions & 0 deletions test/specs/plugin.legend.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,37 @@ describe('Legend block tests', function() {
});
});

it('should draw items with a custom boxHeight', function() {
var chart = window.acquireChart(
{
type: 'line',
data: {
datasets: [{
label: 'dataset1',
data: []
}],
labels: []
},
options: {
legend: {
position: 'right',
labels: {
boxHeight: 40
}
}
}
},
{
canvas: {
width: 512,
height: 105
}
}
);
const hitBox = chart.legend.legendHitBoxes[0];
expect(hitBox.height).toBe(40);
});

it('should pick up the first item when the property is an array', function() {
var chart = window.acquireChart({
type: 'bar',
Expand Down

0 comments on commit 0703d78

Please sign in to comment.