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

Cartesian scale tick backdrop #8931

Merged
merged 1 commit into from Apr 18, 2021
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: 3 additions & 0 deletions docs/axes/_common_ticks.md
Expand Up @@ -4,12 +4,15 @@ Namespace: `options.scales[scaleId].ticks`

| Name | Type | Scriptable | Default | Description
| ---- | ---- | :-------------------------------: | ------- | -----------
| `backdropColor` | [`Color`](../../general/colors.md) | Yes | `'rgba(255, 255, 255, 0.75)'` | Color of label backdrops.
| `backdropPadding` | [`Padding`](../../general/padding.md) | Yes | `2` | Padding of label backdrop.
| `callback` | `function` | | | Returns the string representation of the tick value as it should be displayed on the chart. See [callback](/axes/labelling.md#creating-custom-tick-formats).
| `display` | `boolean` | | `true` | If true, show tick labels.
| `color` | [`Color`](/general/colors.md) | Yes | `Chart.defaults.color` | Color of ticks.
| `font` | `Font` | Yes | `Chart.defaults.font` | See [Fonts](/general/fonts.md)
| `major` | `object` | | `{}` | [Major ticks configuration](/axes/styling.md#major-tick-configuration).
| `padding` | `number` | | `3` | Sets the offset of the tick labels from the axis
| `showLabelBackdrop` | `boolean` | Yes | `true` for radial scale, `false` otherwise | If true, draw a background behind the tick labels.
| `textStrokeColor` | [`Color`](/general/colors.md) | Yes | `` | The color of the stroke around the text.
| `textStrokeWidth` | `number` | Yes | `0` | Stroke width around the text.
| `z` | `number` | | `0` | z-index of tick layer. Useful when ticks are drawn on chart area. Values <= 0 are drawn under datasets, > 0 on top.
3 changes: 0 additions & 3 deletions docs/axes/radial/linear.md
Expand Up @@ -28,14 +28,11 @@ Namespace: `options.scales[scaleId].ticks`

| Name | Type | Scriptable | Default | Description
| ---- | ---- | ------- | ------- | -----------
| `backdropColor` | [`Color`](../../general/colors.md) | Yes | `'rgba(255, 255, 255, 0.75)'` | Color of label backdrops.
| `backdropPadding` | [`Padding`](../../general/padding.md) | Yes | `2` | Padding of label backdrop.
| `count` | `number` | Yes | `undefined` | The number of ticks to generate. If specified, this overrides the automatic generation.
| `format` | `object` | Yes | | The [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) options used by the default label formatter
| `maxTicksLimit` | `number` | Yes | `11` | Maximum number of ticks and gridlines to show.
| `precision` | `number` | Yes | | if defined and `stepSize` is not specified, the step size will be rounded to this many decimal places.
| `stepSize` | `number` | Yes | | User defined fixed step size for the scale. [more...](#step-size)
| `showLabelBackdrop` | `boolean` | Yes | `true` | If true, draw a background behind the tick labels.

!!!include(axes/_common_ticks.md)!!!

Expand Down
4 changes: 4 additions & 0 deletions src/core/core.scale.defaults.js
Expand Up @@ -71,6 +71,10 @@ defaults.set('scale', {
major: {},
align: 'center',
crossAlign: 'near',

showLabelBackdrop: false,
backdropColor: 'rgba(255, 255, 255, 0.75)',
backdropPadding: 2,
}
});

Expand Down
59 changes: 55 additions & 4 deletions src/core/core.scale.js
Expand Up @@ -773,7 +773,7 @@ export default class Scale extends Element {
}

/**
* @return {{ first: object, last: object, widest: object, highest: object }}
* @return {{ first: object, last: object, widest: object, highest: object, widths: Array, heights: array }}
* @private
*/
_getLabelSizes() {
Expand All @@ -796,7 +796,7 @@ export default class Scale extends Element {
/**
* Returns {width, height, offset} objects for the first, last, widest, highest tick
* labels where offset indicates the anchor point offset from the top in pixels.
* @return {{ first: object, last: object, widest: object, highest: object }}
* @return {{ first: object, last: object, widest: object, highest: object, widths: Array, heights: array }}
* @private
*/
_computeLabelSizes(ticks, length) {
Expand Down Expand Up @@ -845,7 +845,9 @@ export default class Scale extends Element {
first: valueAt(0),
last: valueAt(length - 1),
widest: valueAt(widest),
highest: valueAt(highest)
highest: valueAt(highest),
widths,
heights,
};
}

Expand Down Expand Up @@ -1226,6 +1228,48 @@ export default class Scale extends Element {
textOffset = (1 - lineCount) * lineHeight / 2;
}

let backdrop;

if (optsAtIndex.showLabelBackdrop) {
const labelPadding = toPadding(optsAtIndex.backdropPadding);
const height = labelSizes.heights[i];
const width = labelSizes.widths[i];

let top = y + textOffset - labelPadding.top;
let left = x - labelPadding.left;

switch (textBaseline) {
case 'middle':
top -= height / 2;
break;
case 'bottom':
top -= height;
break;
default:
break;
}

switch (textAlign) {
case 'center':
left -= width / 2;
break;
case 'right':
left -= width;
break;
default:
break;
}

backdrop = {
left,
top,
width: width + labelPadding.width,
height: height + labelPadding.height,

color: optsAtIndex.backdropColor,
};
}

items.push({
rotation,
label,
Expand All @@ -1236,7 +1280,8 @@ export default class Scale extends Element {
textOffset,
textAlign,
textBaseline,
translation: [x, y]
translation: [x, y],
backdrop,
});
}

Expand Down Expand Up @@ -1466,6 +1511,12 @@ export default class Scale extends Element {
const item = items[i];
const tickFont = item.font;
const label = item.label;

if (item.backdrop) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this happens before label rotation, angled labels are not properly overlapped. Opening a PR for a fix soon.

ctx.fillStyle = item.backdrop.color;
ctx.fillRect(item.backdrop.left, item.backdrop.top, item.backdrop.width, item.backdrop.height);
}

let y = item.textOffset;
renderText(ctx, label, 0, y, tickFont, item);
}
Expand Down
6 changes: 0 additions & 6 deletions src/scales/scale.radialLinear.js
Expand Up @@ -594,12 +594,6 @@ RadialLinearScale.defaults = {
// Boolean - Show a backdrop to the scale label
showLabelBackdrop: true,

// String - The colour of the label backdrop
backdropColor: 'rgba(255,255,255,0.75)',

// Number/Object - The backdrop padding of the label in pixels
backdropPadding: 2,

callback: Ticks.formatters.numeric
},

Expand Down
76 changes: 76 additions & 0 deletions test/fixtures/core.scale/tick-backdrop.js
@@ -0,0 +1,76 @@
const grid = {
display: false
};
const title = {
display: false,
};
module.exports = {
config: {
type: 'line',
options: {
events: [],
scales: {
top: {
type: 'linear',
position: 'top',
ticks: {
display: true,
showLabelBackdrop: true,
backdropColor: 'red',
backdropPadding: 5,
align: 'start',
crossAlign: 'near',
},
grid,
title
},
left: {
type: 'linear',
position: 'left',
ticks: {
display: true,
showLabelBackdrop: true,
backdropColor: 'green',
backdropPadding: 5,
crossAlign: 'center',
},
grid,
title
},
bottom: {
type: 'linear',
position: 'bottom',
ticks: {
display: true,
showLabelBackdrop: true,
backdropColor: 'blue',
backdropPadding: 5,
align: 'end',
crossAlign: 'far',
},
grid,
title
},
right: {
type: 'linear',
position: 'right',
ticks: {
display: true,
showLabelBackdrop: true,
backdropColor: 'gray',
backdropPadding: 5,
},
grid,
title
},
}
}
},
options: {
canvas: {
height: 256,
width: 256
},
spriteText: true,
}
};
Binary file added test/fixtures/core.scale/tick-backdrop.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 0 additions & 2 deletions test/specs/scale.radialLinear.tests.js
Expand Up @@ -36,8 +36,6 @@ describe('Test the radial linear scale', function() {
ticks: {
color: Chart.defaults.color,
showLabelBackdrop: true,
backdropColor: 'rgba(255,255,255,0.75)',
backdropPadding: 2,
callback: defaultConfig.ticks.callback
},

Expand Down
33 changes: 16 additions & 17 deletions types/index.esm.d.ts
Expand Up @@ -2693,6 +2693,17 @@ export interface GridLineOptions {
}

export interface TickOptions {
/**
* Color of label backdrops.
* @default 'rgba(255, 255, 255, 0.75)'
*/
backdropColor: Scriptable<Color, ScriptableScaleContext>;
/**
* Padding of tick backdrop.
* @default 2
*/
backdropPadding: number | ChartArea;

/**
* Returns the string representation of the tick value as it should be displayed on the chart. See callback.
*/
Expand All @@ -2715,6 +2726,11 @@ export interface TickOptions {
* Sets the offset of the tick labels from the axis
*/
padding: number;
/**
* If true, draw a background behind the tick labels.
* @default false
*/
showLabelBackdrop: Scriptable<boolean, ScriptableScaleContext>;
/**
* The color of the stroke around the text.
* @default undefined
Expand Down Expand Up @@ -3116,17 +3132,6 @@ export type RadialLinearScaleOptions = CoreScaleOptions & {
suggestedMin: number;

ticks: TickOptions & {
/**
* Color of label backdrops.
* @default 'rgba(255, 255, 255, 0.75)'
*/
backdropColor: Scriptable<Color, ScriptableScaleContext>;
/**
* Padding of label backdrop.
* @default 2
*/
backdropPadding: number | ChartArea;

/**
* The Intl.NumberFormat options used by the default label formatter
*/
Expand All @@ -3152,12 +3157,6 @@ export type RadialLinearScaleOptions = CoreScaleOptions & {
* User defined number of ticks
*/
count: number;

/**
* If true, draw a background behind the tick labels.
* @default true
*/
showLabelBackdrop: Scriptable<boolean, ScriptableScaleContext>;
};
};

Expand Down