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 1375f50cb..145f083d9 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 3e2860ffd..8d9006804 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 8282b3a94..a23dce715 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 7b59d9493..419a8b876 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 000000000..b24472a68 --- /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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 literal 0 Hc-jL100001 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 000000000..170719d84 --- /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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 MJpsEbcTvCo1KdE^e*gdg literal 0 Hc-jL100001 diff --git a/test/specs/plugin.tooltip.tests.js b/test/specs/plugin.tooltip.tests.js index 20ca9428b..8060514bc 100644 --- a/test/specs/plugin.tooltip.tests.js +++ b/test/specs/plugin.tooltip.tests.js @@ -156,10 +156,18 @@ describe('Plugin.Tooltip', function() { footer: [], labelColors: [{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }, { borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }] })); @@ -307,7 +315,11 @@ describe('Plugin.Tooltip', function() { expect(tooltip.labelColors).toEqual([{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }]); expect(tooltip.x).toBeCloseToPixel(267); @@ -460,10 +472,18 @@ describe('Plugin.Tooltip', function() { labelTextColors: ['labelTextColor', 'labelTextColor'], labelColors: [{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }, { borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }], labelPointStyles: [{ pointStyle: 'labelPointStyle', @@ -573,10 +593,18 @@ describe('Plugin.Tooltip', function() { footer: [], labelColors: [{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }, { borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }] })); @@ -641,10 +669,18 @@ describe('Plugin.Tooltip', function() { footer: [], labelColors: [{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }, { borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }] })); @@ -710,10 +746,18 @@ describe('Plugin.Tooltip', function() { footer: [], labelColors: [{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }, { borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }] })); @@ -778,7 +822,11 @@ describe('Plugin.Tooltip', function() { footer: [], labelColors: [{ borderColor: defaults.borderColor, - backgroundColor: defaults.backgroundColor + backgroundColor: defaults.backgroundColor, + borderWidth: 1, + borderDash: undefined, + borderDashOffset: undefined, + borderRadius: 0, }] })); }); diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index 01415b273..71f01be03 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -2246,7 +2246,34 @@ export interface TitleOptions { export type TooltipXAlignment = 'left' | 'center' | 'right'; export type TooltipYAlignment = 'top' | 'center' | 'bottom'; +export interface TooltipLabelStyle { + borderColor: Color; + backgroundColor: Color; + + /** + * Width of border line + * @since 3.1.0 + */ + borderWidth?: number; + + /** + * Border dash + * @since 3.1.0 + */ + borderDash?: [number, number]; + + /** + * Border dash offset + * @since 3.1.0 + */ + borderDashOffset?: number; + /** + * borderRadius + * @since 3.1.0 + */ + borderRadius?: number | BorderRadius; +} export interface TooltipModel { // 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 }; -- 2.47.3