From 7ee498e4124599b22b2b15fa13399baab5a9ccf0 Mon Sep 17 00:00:00 2001 From: Evert Timberg Date: Sat, 10 Apr 2021 13:37:22 -0400 Subject: [PATCH] Tooltip colorbox supports configurable borderWidth, borderRadius, and dash effect (#8874) * Start on extending tooltip style * Correct borderRadius implementation * Tests of updated tooltip styling * Update docs --- docs/configuration/tooltip.md | 9 +- src/elements/element.bar.js | 35 +------- src/helpers/helpers.canvas.js | 33 ++++++++ src/plugins/plugin.tooltip.js | 61 +++++++++++--- .../plugin.tooltip/color-box-border-dash.js | 75 +++++++++++++++++ .../plugin.tooltip/color-box-border-dash.png | Bin 0 -> 4890 bytes .../plugin.tooltip/color-box-border-radius.js | 78 ++++++++++++++++++ .../color-box-border-radius.png | Bin 0 -> 4885 bytes test/specs/plugin.tooltip.tests.js | 72 +++++++++++++--- types/index.esm.d.ts | 33 +++++++- 10 files changed, 333 insertions(+), 63 deletions(-) create mode 100644 test/fixtures/plugin.tooltip/color-box-border-dash.js create mode 100644 test/fixtures/plugin.tooltip/color-box-border-dash.png create mode 100644 test/fixtures/plugin.tooltip/color-box-border-radius.js create mode 100644 test/fixtures/plugin.tooltip/color-box-border-radius.png diff --git a/docs/configuration/tooltip.md b/docs/configuration/tooltip.md index 1375f50cbb3..145f083d90e 100644 --- a/docs/configuration/tooltip.md +++ b/docs/configuration/tooltip.md @@ -153,7 +153,7 @@ var chart = new Chart(ctx, { ### Label Color Callback -For example, to return a red box for each item in the tooltip you could do: +For example, to return a red box with a blue dashed border that has a border radius for each item in the tooltip you could do: ```javascript var chart = new Chart(ctx, { @@ -165,8 +165,11 @@ var chart = new Chart(ctx, { callbacks: { labelColor: function(context) { return { - borderColor: 'rgb(255, 0, 0)', - backgroundColor: 'rgb(255, 0, 0)' + borderColor: 'rgb(0, 0, 255)', + backgroundColor: 'rgb(255, 0, 0)', + borderWidth: 2, + borderDash: [2, 2], + borderRadius: 2, }; }, labelTextColor: function(context) { diff --git a/src/elements/element.bar.js b/src/elements/element.bar.js index 3e2860ffd4d..8d900680435 100644 --- a/src/elements/element.bar.js +++ b/src/elements/element.bar.js @@ -1,6 +1,6 @@ import Element from '../core/core.element'; +import {addRoundedRectPath} from '../helpers/helpers.canvas'; import {toTRBL, toTRBLCorners} from '../helpers/helpers.options'; -import {PI, HALF_PI} from '../helpers/helpers.math'; /** * Helper function to get the bounds of the bar regardless of the orientation @@ -141,39 +141,6 @@ function hasRadius(radius) { return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight; } -/** - * Add a path of a rectangle with rounded corners to the current sub-path - * @param {CanvasRenderingContext2D} ctx Context - * @param {*} rect Bounding rect - */ -function addRoundedRectPath(ctx, rect) { - const {x, y, w, h, radius} = rect; - - // top left arc - ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, -HALF_PI, PI, true); - - // line from top left to bottom left - ctx.lineTo(x, y + h - radius.bottomLeft); - - // bottom left arc - ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true); - - // line from bottom left to bottom right - ctx.lineTo(x + w - radius.bottomRight, y + h); - - // bottom right arc - ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true); - - // line from bottom right to top right - ctx.lineTo(x + w, y + radius.topRight); - - // top right arc - ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true); - - // line from top right to top left - ctx.lineTo(x + radius.topLeft, y); -} - /** * Add a path of a rectangle to the current sub-path * @param {CanvasRenderingContext2D} ctx Context diff --git a/src/helpers/helpers.canvas.js b/src/helpers/helpers.canvas.js index 8282b3a9425..a23dce715a5 100644 --- a/src/helpers/helpers.canvas.js +++ b/src/helpers/helpers.canvas.js @@ -377,3 +377,36 @@ export function renderText(ctx, text, x, y, font, opts = {}) { ctx.restore(); } + +/** + * Add a path of a rectangle with rounded corners to the current sub-path + * @param {CanvasRenderingContext2D} ctx Context + * @param {*} rect Bounding rect + */ +export function addRoundedRectPath(ctx, rect) { + const {x, y, w, h, radius} = rect; + + // top left arc + ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, -HALF_PI, PI, true); + + // line from top left to bottom left + ctx.lineTo(x, y + h - radius.bottomLeft); + + // bottom left arc + ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true); + + // line from bottom left to bottom right + ctx.lineTo(x + w - radius.bottomRight, y + h); + + // bottom right arc + ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true); + + // line from bottom right to top right + ctx.lineTo(x + w, y + radius.topRight); + + // top right arc + ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true); + + // line from top right to top left + ctx.lineTo(x + radius.topLeft, y); +} diff --git a/src/plugins/plugin.tooltip.js b/src/plugins/plugin.tooltip.js index 7b59d94938f..419a8b8767c 100644 --- a/src/plugins/plugin.tooltip.js +++ b/src/plugins/plugin.tooltip.js @@ -1,7 +1,8 @@ import Animations from '../core/core.animations'; import Element from '../core/core.element'; +import {addRoundedRectPath} from '../helpers/helpers.canvas'; import {each, noop, isNullOrUndef, isArray, _elementsEqual} from '../helpers/helpers.core'; -import {toFont, toPadding} from '../helpers/helpers.options'; +import {toFont, toPadding, toTRBLCorners} from '../helpers/helpers.options'; import {getRtlAdapter, overrideTextDirection, restoreTextDirection} from '../helpers/helpers.rtl'; import {distanceBetweenPoints, _limitValue} from '../helpers/helpers.math'; import {drawPoint} from '../helpers'; @@ -377,6 +378,8 @@ export class Tooltip extends Element { this.width = undefined; this.caretX = undefined; this.caretY = undefined; + // TODO: V4, make this private, rename to `_labelStyles`, and combine with `labelPointStyles` + // and `labelTextColors` to create a single variable this.labelColors = undefined; this.labelPointStyles = undefined; this.labelTextColors = undefined; @@ -709,18 +712,50 @@ export class Tooltip extends Element { ctx.fillStyle = labelColors.backgroundColor; drawPoint(ctx, drawOptions, centerX, centerY); } else { - // Fill a white rect so that colours merge nicely if the opacity is < 1 - ctx.fillStyle = options.multiKeyBackground; - ctx.fillRect(rtlHelper.leftForLtr(rtlColorX, boxWidth), colorY, boxWidth, boxHeight); - // Border - ctx.lineWidth = 1; + ctx.lineWidth = labelColors.borderWidth || 1; // TODO, v4 remove fallback ctx.strokeStyle = labelColors.borderColor; - ctx.strokeRect(rtlHelper.leftForLtr(rtlColorX, boxWidth), colorY, boxWidth, boxHeight); + ctx.setLineDash(labelColors.borderDash || []); + ctx.lineDashOffset = labelColors.borderDashOffset || 0; - // Inner square - ctx.fillStyle = labelColors.backgroundColor; - ctx.fillRect(rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2), colorY + 1, boxWidth - 2, boxHeight - 2); + // Fill a white rect so that colours merge nicely if the opacity is < 1 + const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth); + const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - 2); + const borderRadius = toTRBLCorners(labelColors.borderRadius); + + if (Object.values(borderRadius).some(v => v !== 0)) { + ctx.beginPath(); + ctx.fillStyle = options.multiKeyBackground; + addRoundedRectPath(ctx, { + x: outerX, + y: colorY, + w: boxWidth, + h: boxHeight, + radius: borderRadius, + }); + ctx.fill(); + ctx.stroke(); + + // Inner square + ctx.fillStyle = labelColors.backgroundColor; + ctx.beginPath(); + addRoundedRectPath(ctx, { + x: innerX, + y: colorY + 1, + w: boxWidth - 2, + h: boxHeight - 2, + radius: borderRadius, + }); + ctx.fill(); + } else { + // Normal rect + ctx.fillStyle = options.multiKeyBackground; + ctx.fillRect(outerX, colorY, boxWidth, boxHeight); + ctx.strokeRect(outerX, colorY, boxWidth, boxHeight); + // Inner square + ctx.fillStyle = labelColors.backgroundColor; + ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2); + } } // restore fillStyle @@ -1197,7 +1232,11 @@ export default { const options = meta.controller.getStyle(tooltipItem.dataIndex); return { borderColor: options.borderColor, - backgroundColor: options.backgroundColor + backgroundColor: options.backgroundColor, + borderWidth: options.borderWidth, + borderDash: options.borderDash, + borderDashOffset: options.borderDashOffset, + borderRadius: 0, }; }, labelTextColor() { diff --git a/test/fixtures/plugin.tooltip/color-box-border-dash.js b/test/fixtures/plugin.tooltip/color-box-border-dash.js new file mode 100644 index 00000000000..b24472a681b --- /dev/null +++ b/test/fixtures/plugin.tooltip/color-box-border-dash.js @@ -0,0 +1,75 @@ +module.exports = { + config: { + type: 'line', + data: { + datasets: [{ + data: [8, 7, 6, 5], + pointBorderColor: '#ff0000', + pointBackgroundColor: '#00ff00', + showLine: false + }], + labels: ['', '', '', ''] + }, + options: { + scales: { + x: {display: false}, + y: {display: false} + }, + elements: { + line: { + fill: false + } + }, + plugins: { + legend: false, + title: false, + filler: false, + tooltip: { + mode: 'nearest', + intersect: false, + callbacks: { + label: function() { + return '\u200b'; + }, + labelColor: function(tooltipItem) { + const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex); + const options = meta.controller.getStyle(tooltipItem.dataIndex); + return { + borderColor: options.borderColor, + backgroundColor: options.backgroundColor, + borderWidth: 2, + borderDash: [2, 2] + }; + }, + } + }, + }, + + layout: { + padding: 15 + } + }, + plugins: [{ + afterDraw: function(chart) { + const canvas = chart.canvas; + const rect = canvas.getBoundingClientRect(); + const point = chart.getDatasetMeta(0).data[1]; + const 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: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/plugin.tooltip/color-box-border-dash.png b/test/fixtures/plugin.tooltip/color-box-border-dash.png new file mode 100644 index 0000000000000000000000000000000000000000..8eb6868f8b3856ba58e90ee0897e6aaed59c1d39 GIT binary patch literal 4890 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 Cknvpr literal 0 HcmV?d00001 diff --git a/test/fixtures/plugin.tooltip/color-box-border-radius.js b/test/fixtures/plugin.tooltip/color-box-border-radius.js new file mode 100644 index 00000000000..170719d8469 --- /dev/null +++ b/test/fixtures/plugin.tooltip/color-box-border-radius.js @@ -0,0 +1,78 @@ +module.exports = { + config: { + type: 'line', + data: { + datasets: [{ + data: [8, 7, 6, 5], + pointBorderColor: '#ff0000', + pointBackgroundColor: '#00ff00', + showLine: false + }], + labels: ['', '', '', ''] + }, + options: { + scales: { + x: {display: false}, + y: {display: false} + }, + elements: { + line: { + fill: false + } + }, + plugins: { + legend: false, + title: false, + filler: false, + tooltip: { + mode: 'nearest', + intersect: false, + callbacks: { + label: function() { + return '\u200b'; + }, + labelColor: function(tooltipItem) { + const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex); + const options = meta.controller.getStyle(tooltipItem.dataIndex); + return { + borderColor: options.borderColor, + backgroundColor: options.backgroundColor, + borderWidth: 2, + borderRadius: { + topRight: 5, + bottomRight: 5, + }, + }; + }, + } + }, + }, + + layout: { + padding: 15 + } + }, + plugins: [{ + afterDraw: function(chart) { + const canvas = chart.canvas; + const rect = canvas.getBoundingClientRect(); + const point = chart.getDatasetMeta(0).data[1]; + const 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: { + canvas: { + height: 256, + width: 512 + } + } +}; diff --git a/test/fixtures/plugin.tooltip/color-box-border-radius.png b/test/fixtures/plugin.tooltip/color-box-border-radius.png new file mode 100644 index 0000000000000000000000000000000000000000..f59f62849940e117b141288ca1c1a113e79a7a1f GIT binary patch literal 4885 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 { // The items that we are rendering in the tooltip. See Tooltip Item Interface section dataPoints: TooltipItem[]; @@ -2284,8 +2311,8 @@ export interface TooltipModel { // lines of text that form the footer footer: string[]; - // colors to render for each item in body[]. This is the color of the squares in the tooltip - labelColors: Color[]; + // Styles to render for each item in body[]. This is the styling of the squares in the tooltip + labelColors: TooltipLabelStyle[]; labelTextColors: Color[]; labelPointStyles: { pointStyle: PointStyle; rotation: number }[]; @@ -2321,7 +2348,7 @@ export interface TooltipCallbacks< label(this: Model, tooltipItem: Item): string | string[]; afterLabel(this: Model, tooltipItem: Item): string | string[]; - labelColor(this: Model, tooltipItem: Item): { borderColor: Color; backgroundColor: Color }; + labelColor(this: Model, tooltipItem: Item): TooltipLabelStyle; labelTextColor(this: Model, tooltipItem: Item): Color; labelPointStyle(this: Model, tooltipItem: Item): { pointStyle: PointStyle; rotation: number };