mirror of
https://github.com/chartjs/Chart.js.git
synced 2026-03-12 19:26:49 +01:00
Enable per-corner border radius in tooltip (#9620)
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
78
test/fixtures/plugin.tooltip/corner-radius.js
vendored
Normal file
78
test/fixtures/plugin.tooltip/corner-radius.js
vendored
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
};
|
||||
BIN
test/fixtures/plugin.tooltip/corner-radius.png
vendored
Normal file
BIN
test/fixtures/plugin.tooltip/corner-radius.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
2
types/index.esm.d.ts
vendored
2
types/index.esm.d.ts
vendored
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user