Skip to content

Commit 7ec80c6

Browse files
committed
Add textAlign for legend labels
1 parent 416062b commit 7ec80c6

File tree

17 files changed

+242
-15
lines changed

17 files changed

+242
-15
lines changed

docs/docs/configuration/legend.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Namespace: `options.plugins.legend.labels`
6262
| `filter` | `function` | `null` | Filters legend items out of the legend. Receives 2 parameters, a [Legend Item](#legend-item-interface) and the chart data.
6363
| `sort` | `function` | `null` | Sorts legend items. Receives 3 parameters, two [Legend Items](#legend-item-interface) and the chart data.
6464
| `pointStyle` | | | If specified, this style of point is used for the legend. Only used if `usePointStyle` is true.
65+
| `textAlign` | `string` | `'center'` | Horizontal alignment of the label text. Options are: `'left'`, `'right'` or `'center'`.
6566
| `usePointStyle` | `boolean` | `false` | Label style will match corresponding point style (size is based on the minimum value between boxWidth and font.size).
6667

6768
## Legend Title Configuration

src/helpers/helpers.extras.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,19 @@ export function debounce(fn, delay) {
6868
export const _toLeftRightCenter = (align) => align === 'start' ? 'left' : align === 'end' ? 'right' : 'center';
6969

7070
/**
71-
* Returns `start`, `end` or `(start + end) / 2` depending on `align`
71+
* Returns `start`, `end` or `(start + end) / 2` depending on `align`. Defaults to `center`
7272
* @param {string} align start, end, center
7373
* @param {number} start value for start
7474
* @param {number} end value for end
7575
* @private
7676
*/
7777
export const _alignStartEnd = (align, start, end) => align === 'start' ? start : align === 'end' ? end : (start + end) / 2;
78+
79+
/**
80+
* Returns `left`, `right` or `(left + right) / 2` depending on `align`. Defaults to `left`
81+
* @param {string} align start, end, center
82+
* @param {number} left value for start
83+
* @param {number} right value for end
84+
* @private
85+
*/
86+
export const _textX = (align, left, right) => align === 'right' ? right : align === 'center' ? (left + right) / 2 : left;

src/plugins/plugin.legend.js

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import Element from '../core/core.element';
33
import layouts from '../core/core.layouts';
44
import {drawPoint, renderText} from '../helpers/helpers.canvas';
55
import {
6-
callback as call, valueOrDefault, toFont, isObject,
6+
callback as call, valueOrDefault, toFont,
77
toPadding, getRtlAdapter, overrideTextDirection, restoreTextDirection,
88
clipArea, unclipArea
99
} from '../helpers/index';
10-
import {_toLeftRightCenter, _alignStartEnd} from '../helpers/helpers.extras';
10+
import {_toLeftRightCenter, _alignStartEnd, _textX} from '../helpers/helpers.extras';
1111
/**
1212
* @typedef { import("../platform/platform.base").ChartEvent } ChartEvent
1313
*/
@@ -244,6 +244,7 @@ export class Legend extends Element {
244244
const labelFont = toFont(labelOpts.font);
245245
const {color: fontColor, padding} = labelOpts;
246246
const fontSize = labelFont.size;
247+
const halfFontSize = fontSize / 2;
247248
let cursor;
248249

249250
me.drawTitle();
@@ -287,7 +288,7 @@ export class Legend extends Element {
287288
borderWidth: lineWidth
288289
};
289290
const centerX = rtlHelper.xPlus(x, boxWidth / 2);
290-
const centerY = y + fontSize / 2;
291+
const centerY = y + halfFontSize;
291292

292293
// Draw pointStyle as legend symbol
293294
drawPoint(ctx, drawOptions, centerX, centerY);
@@ -306,9 +307,10 @@ export class Legend extends Element {
306307
};
307308

308309
const fillText = function(x, y, legendItem) {
309-
const halfFontSize = fontSize / 2;
310-
const xLeft = rtlHelper.xPlus(x, boxWidth + halfFontSize);
311-
renderText(ctx, legendItem.text, xLeft, y + (itemHeight / 2), labelFont, {strikethrough: legendItem.hidden});
310+
renderText(ctx, legendItem.text, x, y + (itemHeight / 2), labelFont, {
311+
strikethrough: legendItem.hidden,
312+
textAlign: legendItem.textAlign
313+
});
312314
};
313315

314316
// Horizontal
@@ -333,6 +335,7 @@ export class Legend extends Element {
333335
const lineHeight = itemHeight + padding;
334336
me.legendItems.forEach((legendItem, i) => {
335337
const textWidth = ctx.measureText(legendItem.text).width;
338+
const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));
336339
const width = boxWidth + (fontSize / 2) + textWidth;
337340
let x = cursor.x;
338341
let y = cursor.y;
@@ -358,8 +361,10 @@ export class Legend extends Element {
358361
legendHitBoxes[i].left = rtlHelper.leftForLtr(realX, legendHitBoxes[i].width);
359362
legendHitBoxes[i].top = y;
360363

364+
x = _textX(textAlign, x + boxWidth + halfFontSize, me.right);
365+
361366
// Fill the actual label
362-
fillText(realX, y, legendItem);
367+
fillText(rtlHelper.x(x), y, legendItem);
363368

364369
if (isHorizontal) {
365370
cursor.x += width + padding;
@@ -577,13 +582,11 @@ export default {
577582
// lineWidth :
578583
generateLabels(chart) {
579584
const datasets = chart.data.datasets;
580-
const {labels} = chart.legend.options;
581-
const usePointStyle = labels.usePointStyle;
582-
const overrideStyle = labels.pointStyle;
585+
const {labels: {usePointStyle, pointStyle, textAlign}} = chart.legend.options;
583586

584587
return chart._getSortedDatasetMetas().map((meta) => {
585588
const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
586-
const borderWidth = isObject(style.borderWidth) ? (valueOrDefault(style.borderWidth.top, 0) + valueOrDefault(style.borderWidth.left, 0) + valueOrDefault(style.borderWidth.bottom, 0) + valueOrDefault(style.borderWidth.right, 0)) / 4 : style.borderWidth;
589+
const borderWidth = toPadding(style.borderWidth);
587590

588591
return {
589592
text: datasets[meta.index].label,
@@ -593,10 +596,11 @@ export default {
593596
lineDash: style.borderDash,
594597
lineDashOffset: style.borderDashOffset,
595598
lineJoin: style.borderJoinStyle,
596-
lineWidth: borderWidth,
599+
lineWidth: (borderWidth.width + borderWidth.height) / 4,
597600
strokeStyle: style.borderColor,
598-
pointStyle: overrideStyle || style.pointStyle,
601+
pointStyle: pointStyle || style.pointStyle,
599602
rotation: style.rotation,
603+
textAlign: textAlign || style.textAlign,
600604

601605
// Below is extra data used for toggling the datasets
602606
datasetIndex: meta.index
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
config: {
3+
type: 'pie',
4+
data: {
5+
labels: ['aaaa', 'bb', 'c'],
6+
datasets: [
7+
{
8+
data: [1, 2, 3]
9+
}
10+
]
11+
},
12+
options: {
13+
plugins: {
14+
legend: {
15+
position: 'right',
16+
labels: {
17+
textAlign: 'center'
18+
}
19+
}
20+
}
21+
}
22+
},
23+
options: {
24+
spriteText: true,
25+
canvas: {
26+
width: 256,
27+
height: 256
28+
}
29+
}
30+
};
10.6 KB
Loading
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
config: {
3+
type: 'pie',
4+
data: {
5+
labels: ['aaaa', 'bb', 'c'],
6+
datasets: [
7+
{
8+
data: [1, 2, 3]
9+
}
10+
]
11+
},
12+
options: {
13+
plugins: {
14+
legend: {
15+
position: 'right',
16+
labels: {
17+
textAlign: 'left'
18+
}
19+
}
20+
}
21+
}
22+
},
23+
options: {
24+
spriteText: true,
25+
canvas: {
26+
width: 256,
27+
height: 256
28+
}
29+
}
30+
};
10.5 KB
Loading
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
config: {
3+
type: 'pie',
4+
data: {
5+
labels: ['aaaa', 'bb', 'c'],
6+
datasets: [
7+
{
8+
data: [1, 2, 3]
9+
}
10+
]
11+
},
12+
options: {
13+
plugins: {
14+
legend: {
15+
position: 'right',
16+
labels: {
17+
textAlign: 'right'
18+
}
19+
}
20+
}
21+
}
22+
},
23+
options: {
24+
spriteText: true,
25+
canvas: {
26+
width: 256,
27+
height: 256
28+
}
29+
}
30+
};
10.5 KB
Loading
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
module.exports = {
2+
config: {
3+
type: 'pie',
4+
data: {
5+
labels: ['aaaa', 'bb', 'c'],
6+
datasets: [
7+
{
8+
data: [1, 2, 3]
9+
}
10+
]
11+
},
12+
options: {
13+
plugins: {
14+
legend: {
15+
position: 'right',
16+
rtl: true,
17+
labels: {
18+
textAlign: 'center'
19+
}
20+
}
21+
}
22+
}
23+
},
24+
options: {
25+
spriteText: true,
26+
canvas: {
27+
width: 256,
28+
height: 256
29+
}
30+
}
31+
};

0 commit comments

Comments
 (0)