Skip to content

Commit

Permalink
Enable per-corner border radius in tooltip (#9620)
Browse files Browse the repository at this point in the history
  • Loading branch information
etimberg committed Sep 5, 2021
1 parent 6c47a98 commit 0cdadd2
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 18 deletions.
2 changes: 1 addition & 1 deletion docs/configuration/tooltip.md
Expand Up @@ -32,7 +32,7 @@ Namespace: `options.plugins.tooltip`, the global options for the chart tooltips
| `padding` | [`Padding`](../general/padding.md) | `6` | Padding inside the tooltip.
| `caretPadding` | `number` | `2` | Extra distance to move the end of the tooltip arrow away from the tooltip point.
| `caretSize` | `number` | `5` | Size, in px, of the tooltip arrow.
| `cornerRadius` | `number` | `6` | Radius of tooltip corner curves.
| `cornerRadius` | `number`\|`object` | `6` | Radius of tooltip corner curves.
| `multiKeyBackground` | [`Color`](../general/colors.md) | `'#fff'` | Color to draw behind the colored boxes when multiple items are in the tooltip.
| `displayColors` | `boolean` | `true` | If true, color boxes are shown in the tooltip.
| `boxWidth` | `number` | `bodyFont.size` | Width of the color box if displayColors is true.
Expand Down
33 changes: 17 additions & 16 deletions src/plugins/plugin.tooltip.js
Expand Up @@ -294,7 +294,7 @@ function getBackgroundPoint(options, size, alignment, chart) {
const {caretSize, caretPadding, cornerRadius} = options;
const {xAlign, yAlign} = alignment;
const paddingAndSize = caretSize + caretPadding;
const radiusAndPadding = cornerRadius + caretPadding;
const {topLeft, topRight, bottomLeft, bottomRight} = toTRBLCorners(cornerRadius);

let x = alignX(size, xAlign);
const y = alignY(size, yAlign, paddingAndSize);
Expand All @@ -306,9 +306,9 @@ function getBackgroundPoint(options, size, alignment, chart) {
x -= paddingAndSize;
}
} else if (xAlign === 'left') {
x -= radiusAndPadding;
x -= Math.max(topLeft, bottomLeft) + caretPadding;
} else if (xAlign === 'right') {
x += radiusAndPadding;
x += Math.max(topRight, bottomRight) + caretPadding;
}

return {
Expand Down Expand Up @@ -588,7 +588,8 @@ export class Tooltip extends Element {

getCaretPosition(tooltipPoint, size, options) {
const {xAlign, yAlign} = this;
const {cornerRadius, caretSize} = options;
const {caretSize, cornerRadius} = options;
const {topLeft, topRight, bottomLeft, bottomRight} = toTRBLCorners(cornerRadius);
const {x: ptX, y: ptY} = tooltipPoint;
const {width, height} = size;
let x1, x2, x3, y1, y2, y3;
Expand All @@ -615,9 +616,9 @@ export class Tooltip extends Element {
x3 = x1;
} else {
if (xAlign === 'left') {
x2 = ptX + cornerRadius + (caretSize);
x2 = ptX + Math.max(topLeft, bottomLeft) + (caretSize);
} else if (xAlign === 'right') {
x2 = ptX + width - cornerRadius - caretSize;
x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;
} else {
x2 = this.caretX;
}
Expand Down Expand Up @@ -855,34 +856,34 @@ export class Tooltip extends Element {
const {xAlign, yAlign} = this;
const {x, y} = pt;
const {width, height} = tooltipSize;
const radius = options.cornerRadius;
const {topLeft, topRight, bottomLeft, bottomRight} = toTRBLCorners(options.cornerRadius);

ctx.fillStyle = options.backgroundColor;
ctx.strokeStyle = options.borderColor;
ctx.lineWidth = options.borderWidth;

ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.moveTo(x + topLeft, y);
if (yAlign === 'top') {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x + width - radius, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
ctx.lineTo(x + width - topRight, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + topRight);
if (yAlign === 'center' && xAlign === 'right') {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x + width, y + height - radius);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
ctx.lineTo(x + width, y + height - bottomRight);
ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height);
if (yAlign === 'bottom') {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x + radius, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
ctx.lineTo(x + bottomLeft, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft);
if (yAlign === 'center' && xAlign === 'left') {
this.drawCaret(pt, ctx, tooltipSize, options);
}
ctx.lineTo(x, y + radius);
ctx.quadraticCurveTo(x, y, x + radius, y);
ctx.lineTo(x, y + topLeft);
ctx.quadraticCurveTo(x, y, x + topLeft, y);
ctx.closePath();

ctx.fill();
Expand Down
78 changes: 78 additions & 0 deletions test/fixtures/plugin.tooltip/corner-radius.js
@@ -0,0 +1,78 @@
const data = [];
for (let x = 0; x < 3; x++) {
for (let y = 0; y < 3; y++) {
data.push({x, y});
}
}

module.exports = {
config: {
type: 'scatter',
data: {
datasets: [{
data,
backgroundColor: 'red',
radius: 1,
hoverRadius: 0
}],
},
options: {
scales: {
x: {display: false},
y: {display: false}
},
plugins: {
legend: false,
title: false,
filler: false,
tooltip: {
mode: 'point',
intersect: true,
// spriteText: use white background to hide any gaps between fonts
backgroundColor: 'white',
borderColor: 'black',
borderWidth: 1,
callbacks: {
beforeLabel: () => 'before label',
label: () => 'label',
afterLabel: () => 'after1\nafter2\nafter3\nafter4\nafter5'
},
cornerRadius: {
topLeft: 10,
topRight: 20,
bottomRight: 5,
bottomLeft: 0,
}
},
},
},
plugins: [{
afterDraw: function(chart) {
const canvas = chart.canvas;
const rect = canvas.getBoundingClientRect();
const meta = chart.getDatasetMeta(0);
let point, event;

for (let i = 0; i < data.length; i++) {
point = meta.data[i];
event = {
type: 'mousemove',
target: canvas,
clientX: rect.left + point.x,
clientY: rect.top + point.y
};
chart._handleEvent(event);
chart.tooltip.handleEvent(event);
chart.tooltip.draw(chart.ctx);
}
}
}]
},
options: {
spriteText: true,
canvas: {
height: 400,
width: 500
}
}
};
Binary file added test/fixtures/plugin.tooltip/corner-radius.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion types/index.esm.d.ts
Expand Up @@ -2604,7 +2604,7 @@ export interface TooltipOptions<TType extends ChartType = ChartType> extends Cor
* Radius of tooltip corner curves.
* @default 6
*/
cornerRadius: Scriptable<number, ScriptableTooltipContext<TType>>;
cornerRadius: Scriptable<number | BorderRadius, ScriptableTooltipContext<TType>>;
/**
* Color to draw behind the colored boxes when multiple items are in the tooltip.
* @default '#fff'
Expand Down

0 comments on commit 0cdadd2

Please sign in to comment.