From: Evert Timberg Date: Sun, 5 Sep 2021 17:07:28 +0000 (-0400) Subject: Enable per-corner border radius in tooltip (#9620) X-Git-Tag: v3.6.0~39 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0cdadd2560f1a1f0dfbb1d8d65707030415d07cf;p=thirdparty%2FChart.js.git Enable per-corner border radius in tooltip (#9620) --- diff --git a/docs/configuration/tooltip.md b/docs/configuration/tooltip.md index 4874120f1..936f9202c 100644 --- a/docs/configuration/tooltip.md +++ b/docs/configuration/tooltip.md @@ -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. diff --git a/src/plugins/plugin.tooltip.js b/src/plugins/plugin.tooltip.js index b852e7ee4..231506b73 100644 --- a/src/plugins/plugin.tooltip.js +++ b/src/plugins/plugin.tooltip.js @@ -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(); diff --git a/test/fixtures/plugin.tooltip/corner-radius.js b/test/fixtures/plugin.tooltip/corner-radius.js new file mode 100644 index 000000000..e5c98a462 --- /dev/null +++ b/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 + } + } +}; diff --git a/test/fixtures/plugin.tooltip/corner-radius.png b/test/fixtures/plugin.tooltip/corner-radius.png new file mode 100644 index 000000000..0e71cb26f Binary files /dev/null and b/test/fixtures/plugin.tooltip/corner-radius.png differ diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index 58c705974..1e3485e53 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -2604,7 +2604,7 @@ export interface TooltipOptions extends Cor * Radius of tooltip corner curves. * @default 6 */ - cornerRadius: Scriptable>; + cornerRadius: Scriptable>; /** * Color to draw behind the colored boxes when multiple items are in the tooltip. * @default '#fff'