Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pointStyleWidth option for legend #10412

Merged
merged 3 commits into from Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/configuration/legend.md
Expand Up @@ -65,7 +65,8 @@ Namespace: `options.plugins.legend.labels`
| `sort` | `function` | `null` | Sorts legend items. Type is : `sort(a: LegendItem, b: LegendItem, data: ChartData): number;`. Receives 3 parameters, two [Legend Items](#legend-item-interface) and the chart data. The return value of the function is a number that indicates the order of the two legend item parameters. The ordering matches the [return value](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#description) of `Array.prototype.sort()`
| [`pointStyle`](elements.md#point-styles) | [`pointStyle`](elements.md#types) | `'circle'` | If specified, this style of point is used for the legend. Only used if `usePointStyle` is true.
| `textAlign` | `string` | `'center'` | Horizontal alignment of the label text. Options are: `'left'`, `'right'` or `'center'`.
| `usePointStyle` | `boolean` | `false` | Label style will match corresponding point style (size is based on the minimum value between boxWidth and font.size).
| `usePointStyle` | `boolean` | `false` | Label style will match corresponding point style (size is based on pointStyleWidth or the minimum value between boxWidth and font.size).
| `pointStyleWidth` | `number` | `null` | If `usePointStyle` is true, the width of the point style used for the legend (only for `circle`, `rect` and `line` point stlye).

## Legend Title Configuration

Expand Down
17 changes: 13 additions & 4 deletions src/helpers/helpers.canvas.js
Expand Up @@ -127,7 +127,11 @@ export function clearCanvas(canvas, ctx) {
}

export function drawPoint(ctx, options, x, y) {
let type, xOffset, yOffset, size, cornerRadius;
drawPointLegend(ctx, options, x, y, null);
}

export function drawPointLegend(ctx, options, x, y, w) {
let type, xOffset, yOffset, size, cornerRadius, width;
const style = options.pointStyle;
const rotation = options.rotation;
const radius = options.radius;
Expand All @@ -154,7 +158,11 @@ export function drawPoint(ctx, options, x, y) {
switch (style) {
// Default includes circle
default:
ctx.arc(x, y, radius, 0, TAU);
if (w) {
ctx.ellipse(x, y, w / 2, radius, 0, 0, TAU);
} else {
ctx.arc(x, y, radius, 0, TAU);
}
ctx.closePath();
break;
case 'triangle':
Expand Down Expand Up @@ -186,7 +194,8 @@ export function drawPoint(ctx, options, x, y) {
case 'rect':
if (!rotation) {
size = Math.SQRT1_2 * radius;
ctx.rect(x - size, y - size, 2 * size, 2 * size);
width = w ? w / 2 : size;
ctx.rect(x - width, y - size, 2 * width, 2 * size);
break;
}
rad += QUARTER_PI;
Expand Down Expand Up @@ -227,7 +236,7 @@ export function drawPoint(ctx, options, x, y) {
ctx.lineTo(x - yOffset, y + xOffset);
break;
case 'line':
xOffset = Math.cos(rad) * radius;
xOffset = w ? w / 2 : Math.cos(rad) * radius;
yOffset = Math.sin(rad) * radius;
ctx.moveTo(x - xOffset, y - yOffset);
ctx.lineTo(x + xOffset, y + yOffset);
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/plugin.legend.js
@@ -1,7 +1,7 @@
import defaults from '../core/core.defaults';
import Element from '../core/core.element';
import layouts from '../core/core.layouts';
import {addRoundedRectPath, drawPoint, renderText} from '../helpers/helpers.canvas';
import {addRoundedRectPath, drawPointLegend, renderText} from '../helpers/helpers.canvas';
import {
callback as call, valueOrDefault, toFont,
toPadding, getRtlAdapter, overrideTextDirection, restoreTextDirection,
Expand All @@ -18,7 +18,7 @@ const getBoxSize = (labelOpts, fontSize) => {

if (labelOpts.usePointStyle) {
boxHeight = Math.min(boxHeight, fontSize);
boxWidth = Math.min(boxWidth, fontSize);
boxWidth = labelOpts.pointStyleWidth || Math.min(boxWidth, fontSize);
}

return {
Expand Down Expand Up @@ -316,7 +316,7 @@ export class Legend extends Element {
// Recalculate x and y for drawPoint() because its expecting
// x and y to be center of figure (instead of top left)
const drawOptions = {
radius: boxWidth * Math.SQRT2 / 2,
radius: boxHeight * Math.SQRT2 / 2,
pointStyle: legendItem.pointStyle,
rotation: legendItem.rotation,
borderWidth: lineWidth
Expand All @@ -325,7 +325,7 @@ export class Legend extends Element {
const centerY = y + halfFontSize;

// Draw pointStyle as legend symbol
drawPoint(ctx, drawOptions, centerX, centerY);
drawPointLegend(ctx, drawOptions, centerX, centerY, boxWidth);
} else {
// Draw box as legend symbol
// Adjust position when boxHeight < fontSize (want it centered)
Expand Down
2 changes: 2 additions & 0 deletions types/helpers/helpers.canvas.d.ts
Expand Up @@ -18,6 +18,8 @@ export interface DrawPointOptions {

export function drawPoint(ctx: CanvasRenderingContext2D, options: DrawPointOptions, x: number, y: number): void;

export function drawPointLegend(ctx: CanvasRenderingContext2D, options: DrawPointOptions, x: number, y: number, w: number): void;

/**
* Converts the given font object into a CSS font string.
* @param font a font object
Expand Down