From b9cbccf6ec2c3b7f1d9ae4b8af5ce766b4f6b6cb Mon Sep 17 00:00:00 2001 From: stockiNail Date: Sat, 25 Feb 2023 18:44:54 +0100 Subject: [PATCH] Enable different fonts and colors configuration on multiline labels (#801) * Add element diagrams to the annotation types guide * Enable different fonts and colors configuration on multiline labels * updates type definitions * fixes CC * documentation * fixes check for font as array * adds sample * fixes CC * changes font and color as indexable * add tolerance * add tolerance 2 * add tolerance 3 * add tolerance 4 * add tolerance 4 * fallback tolerance changes * Test with new registered fixtures * Another test if adjust is passed * additional test with a label fixture * add new fixture for polygon to test if works * add new fixtures for ellipse from FF * fallback tests on fixtures --- docs/.vuepress/config.js | 1 + docs/guide/types/_commonInnerLabel.md | 10 +- docs/guide/types/label.md | 8 +- docs/guide/types/line.md | 10 +- docs/samples/label/fontsColors.md | 152 ++++++++++++++++++ src/annotation.js | 6 +- src/elements.js | 8 +- src/helpers/helpers.canvas.js | 79 ++++++--- test/fixtures/label/contentMultilineColors.js | 56 +++++++ .../fixtures/label/contentMultilineColors.png | Bin 0 -> 26734 bytes test/fixtures/label/contentMultilineFonts.js | 53 ++++++ test/fixtures/label/contentMultilineFonts.png | Bin 0 -> 25554 bytes types/label.d.ts | 4 +- 13 files changed, 352 insertions(+), 35 deletions(-) create mode 100644 docs/samples/label/fontsColors.md create mode 100644 test/fixtures/label/contentMultilineColors.js create mode 100644 test/fixtures/label/contentMultilineColors.png create mode 100644 test/fixtures/label/contentMultilineFonts.js create mode 100644 test/fixtures/label/contentMultilineFonts.png diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 1133742bd..bdbc82804 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -166,6 +166,7 @@ module.exports = { 'label/image', 'label/innerChart', 'label/lowerUpper', + 'label/fontsColors', 'label/autoscaling' ] }, diff --git a/docs/guide/types/_commonInnerLabel.md b/docs/guide/types/_commonInnerLabel.md index 102dbaf33..b193ba977 100644 --- a/docs/guide/types/_commonInnerLabel.md +++ b/docs/guide/types/_commonInnerLabel.md @@ -6,11 +6,11 @@ All of these options can be [Scriptable](../options.md#scriptable-options) | Name | Type | Default | Notes | ---- | ---- | :----: | ---- -| `color` | [`Color`](../options.md#color) | `'black'` | Text color. +| [`color`](#fonts-and-colors) | [`Color`\|`Color[]`](../options#color) | `'black'` | Text color. | `content` | `string`\|`string[]`\|[`Image`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image)\|[`HTMLCanvasElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) | `null` | The content to show in the label. | `display` | `boolean` | `false` | Whether or not the label is shown. -| `drawTime` | `string` | `options.drawTime` | See [drawTime](../options.md#draw-time). Defaults to the annotation draw time if unset -| `font` | [`Font`](../options.md#font) | `{ weight: 'bold' }` | Label font +| `drawTime` | `string` | `options.drawTime` | See [drawTime](../options#draw-time). Defaults to the annotation draw time if unset +| [`font`](#fonts-and-colors) | [`Font`\|`Font[]`](../options#font) | `{ weight: 'bold' }` | Label font | `height` | `number`\|`string` | `undefined` | Overrides the height of the image or canvas element. Could be set in pixel by a number, or in percentage of current height of image or canvas element by a string. If undefined, uses the height of the image or canvas element. It is used only when the content is an image or canvas element. | `opacity` | `number` | `undefined` | Overrides the opacity of the image or canvas element. Could be set a number in the range 0.0 to 1.0, inclusive. If undefined, uses the opacity of the image or canvas element. It is used only when the content is an image or canvas element. | `padding` | [`Padding`](../options.md#padding) | `6` | The padding to add around the text label. @@ -34,3 +34,7 @@ A position can be set in 2 different values types: If this value is a string (possible options are `'start'`, `'center'`, `'end'` or a string in percentage format), it is applied to vertical and horizontal position in the annotation. If this value is an object, the `x` property defines the horizontal alignment in the annotation. Similarly, the `y` property defines the vertical alignment in the annotation. Possible options for both properties are `'start'`, `'center'`, `'end'`, a string in percentage format. Omitted property have value of the default, `'center'`. + +### Fonts and colors + +When the label to draw has multiple lines, you can use different font and color for each line of the label. This is enabled configuring an array of fonts or colors for those options. When the lines are more than the configured fonts of colors, the last configuration of those options is used for all remaining lines. diff --git a/docs/guide/types/label.md b/docs/guide/types/label.md index d33cbea3a..ae21635a5 100644 --- a/docs/guide/types/label.md +++ b/docs/guide/types/label.md @@ -60,9 +60,9 @@ The following options are available for label annotations. | [`borderRadius`](#borderradius) | `number` \| `object` | Yes | `0` | [`borderWidth`](#styling) | `number`| Yes | `0` | [`callout`](#callout) | `object` | Yes | -| [`color`](#styling) | [`Color`](../options.md#color) | Yes | `'black'` +| [`color`](#styling) | [`Color`\|`Color[]`](../options#color) | Yes | `'black'` | [`content`](#general) | `string`\|`string[]`\|[`Image`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image)\|[`HTMLCanvasElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) | Yes | `null` -| [`font`](#styling) | [`Font`](../options.md#font) | Yes | `{}` +| [`font`](#styling) | [`Font`\|`Font[]`](../options#font) | Yes | `{}` | [`height`](#general) | `number`\|`string` | Yes | `undefined` | [`opacity`](#styling) | `number` | Yes | `undefined` | [`padding`](#general) | [`Padding`](../options.md#padding) | Yes | `6` @@ -122,8 +122,8 @@ The 4 coordinates, xMin, xMax, yMin, yMax are optional. If not specified, the bo | `borderJoinStyle` | Border line join style. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin). | `borderShadowColor` | The color of the border shadow. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor). | `borderWidth` | Stroke width (in pixels). -| `color` | Text color. -| `font` | Text font. +| `color` | Text color. When the label to draw has multiple lines, you can use different color for each line of the label. This is enabled configuring an array of colors. When the lines are more than the configured colors, the last configuration of this option is used for all remaining lines. +| `font` | Text font. When the label to draw has multiple lines, you can use different font for each line of the label. This is enabled configuring an array of fonts. When the lines are more than the configured fonts, the last configuration of this option is used for all remaining lines. | `opacity` | Overrides the opacity of the image or canvas element. Could be set a number in the range 0.0 to 1.0, inclusive. If undefined, uses the opacity of the image or canvas element. It is used only when the content is an image or canvas element. | `shadowBlur` | The amount of blur applied to shadow of the box where the label is located. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowBlur). | `shadowOffsetX` | The distance that shadow, of the box where the label is located, will be offset horizontally. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowOffsetX). diff --git a/docs/guide/types/line.md b/docs/guide/types/line.md index 41ba893b9..7bd13d26e 100644 --- a/docs/guide/types/line.md +++ b/docs/guide/types/line.md @@ -131,11 +131,11 @@ All of these options can be [Scriptable](../options.md#scriptable-options) | `borderShadowColor` | [`Color`](../options.md#color) | `'transparent'` | The color of border shadow of the box where the label is located. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/shadowColor). | `borderWidth` | `number` | `0` | The border line width (in pixels). | [`callout`](#callout) | `object` | | Can connect the label to the line. See [callout](#callout). -| `color` | [`Color`](../options.md#color) | `'#fff'` | Text color. +| [`color`](#fonts-and-colors) | [`Color`\|`Color[]`](../options#color) | `'#fff'` | Text color. | `content` | `string`\|`string[]`\|[`Image`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/Image)\|[`HTMLCanvasElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement) | `null` | The content to show in the label. | `display` | `boolean` | `false` | Whether or not the label is shown. -| `drawTime` | `string` | `options.drawTime` | See [drawTime](../options.md#draw-time). Defaults to the line annotation draw time if unset. -| `font` | [`Font`](../options.md#font) | `{ weight: 'bold' }` | Label font. +| `drawTime` | `string` | `options.drawTime` | See [drawTime](../options#draw-time). Defaults to the line annotation draw time if unset. +| [`font`](#fonts-and-colors) | [`Font`\|`Font[]`](../options#font) | `{ weight: 'bold' }` | Label font. | `height` | `number`\|`string` | `undefined` | Overrides the height of the image or canvas element. Could be set in pixel by a number, or in percentage of current height of image or canvas element by a string. If undefined, uses the height of the image or canvas element. It is used only when the content is an image or canvas element. | `opacity` | `number` | `undefined` | Overrides the opacity of the image or canvas element. Could be set a number in the range 0.0 to 1.0, inclusive. If undefined, uses the opacity of the image or canvas element. It is used only when the content is an image or canvas element. | `padding` | [`Padding`](../options.md#padding) | `6` | The padding to add around the text label. @@ -156,6 +156,10 @@ All of these options can be [Scriptable](../options.md#scriptable-options) If this value is a number, it is applied to all corners of the rectangle (topLeft, topRight, bottomLeft, bottomRight). If this value is an object, the `topLeft` property defines the top-left corners border radius. Similarly, the `topRight`, `bottomLeft`, and `bottomRight` properties can also be specified. Omitted corners have radius of 0. +### Fonts and colors + +When the label to draw has multiple lines, you can use different font and color for each line of the label. This is enabled configuring an array of fonts or colors for those options. When the lines are more than the configured fonts of colors, the last configuration of those options is used for all remaining lines. + ### Callout A callout can connect the label to the line when the label is arbitrarily (by `xAdjust` and `yAdjust` options) moved from its original position. diff --git a/docs/samples/label/fontsColors.md b/docs/samples/label/fontsColors.md new file mode 100644 index 000000000..f52120e76 --- /dev/null +++ b/docs/samples/label/fontsColors.md @@ -0,0 +1,152 @@ +# Fonts and colors + +```js chart-editor +// +const DATA_COUNT = 12; +const MIN = 0; +const MAX = 100; + +const numberCfg = {count: DATA_COUNT, min: MIN, max: MAX}; + +const data = { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + datasets: [{ + data: Utils.numbers(numberCfg) + }] +}; +// + +// +const annotation1 = { + type: 'label', + backgroundColor: 'rgba(0,0,0,0.2)', + borderRadius: 6, + borderWidth: 0, + callout: { + display: true + }, + color: ['black,', 'black', 'green'], + content: ['March', 'is', 'annotated'], + font: [{size: 16, weight: 'bold'}, {family: 'courier'}], + position: { + x: 'center', + y: 'end' + }, + xValue: 'March', + yAdjust: (ctx) => yOffset(ctx, 'March'), + yValue: (ctx) => yValue(ctx, 'March') +}; +// + +// +const annotation2 = { + type: 'label', + backgroundColor: 'rgba(0,0,0,0.2)', + borderRadius: 6, + borderWidth: 0, + callout: { + display: true + }, + color: ['black,', 'black', 'green'], + content: ['June', 'is', 'annotated'], + font: [{size: 16, weight: 'bold'}, {family: 'courier'}], + position: { + x: 'center', + y: 'end' + }, + xValue: 'June', + yAdjust: (ctx) => yOffset(ctx, 'June'), + yValue: (ctx) => yValue(ctx, 'June') +}; +// + +// +const annotation3 = { + type: 'label', + backgroundColor: 'rgba(0,0,0,0.2)', + borderRadius: 6, + borderWidth: 0, + callout: { + display: true + }, + color: ['black,', 'black', 'green'], + content: ['October', 'is', 'annotated'], + font: [{size: 16, weight: 'bold'}, {family: 'courier'}], + position: { + x: 'center', + y: 'end' + }, + xValue: 'October', + yAdjust: (ctx) => yOffset(ctx, 'October'), + yValue: (ctx) => yValue(ctx, 'October') +}; +// + +// +function yValue(ctx, label) { + const chart = ctx.chart; + const dataset = chart.data.datasets[0]; + return dataset.data[chart.data.labels.indexOf(label)]; +} + +function yOffset(ctx, label) { + const value = yValue(ctx, label); + const chart = ctx.chart; + const scale = chart.scales.y; + const y = scale.getPixelForValue(value); + const lblPos = scale.getPixelForValue(100); + return lblPos - y - 5; +} + +// + +/* */ +const config = { + type: 'bar', + data, + options: { + scales: { + y: { + beginAtZero: true, + max: 130, + min: 0, + grid: { + color: (ctx)=> ctx.tick.value <= 100 ? + ctx.chart.scales.x.options.grid.color : + undefined + }, + ticks: { + callback: (value) => value > 100 ? '' : value + } + } + }, + plugins: { + annotation: { + annotations: { + annotation1, + annotation2, + annotation3 + } + } + } + } +}; +/* */ + +const actions = [ + { + name: 'Randomize', + handler: function(chart) { + chart.data.datasets.forEach(function(dataset, i) { + dataset.data = dataset.data.map(() => Utils.rand(MIN, MAX)); + }); + chart.update(); + } + } +]; + +module.exports = { + actions: actions, + config: config, +}; +``` diff --git a/src/annotation.js b/src/annotation.js index 9d8fec04d..5f26c7942 100644 --- a/src/annotation.js +++ b/src/annotation.js @@ -3,7 +3,7 @@ import {clipArea, unclipArea, isObject, isArray} from 'chart.js/helpers'; import {handleEvent, eventHooks, updateListeners} from './events'; import {invokeHook, elementHooks, updateHooks} from './hooks'; import {adjustScaleRange, verifyScaleOptions} from './scale'; -import {updateElements, resolveType} from './elements'; +import {updateElements, resolveType, isIndexable} from './elements'; import {annotationTypes} from './types'; import {requireVersion} from './helpers'; import {version} from '../package.json'; @@ -137,8 +137,10 @@ export default { }, common: { label: { + _indexable: isIndexable, _fallback: true - } + }, + _indexable: isIndexable } }, diff --git a/src/elements.js b/src/elements.js index ba996cc53..d4df1b3db 100644 --- a/src/elements.js +++ b/src/elements.js @@ -16,6 +16,12 @@ const hooks = eventHooks.concat(elementHooks); * @typedef { import('../../types/options').AnnotationPluginOptions } AnnotationPluginOptions */ +/** + * @param {string} prop + * @returns {boolean} + */ +export const isIndexable = (prop) => prop === 'color' || prop === 'font'; + /** * Resolve the annotation type, checking if is supported. * @param {string} [type=line] - annotation type @@ -126,7 +132,7 @@ function resolveObj(resolver, defs) { for (const prop of Object.keys(defs)) { const optDefs = defs[prop]; const value = resolver[prop]; - result[prop] = isObject(optDefs) ? resolveObj(value, optDefs) : value; + result[prop] = isObject(optDefs) && !isIndexable(prop) ? resolveObj(value, optDefs) : value; } return result; } diff --git a/src/helpers/helpers.canvas.js b/src/helpers/helpers.canvas.js index 703231eae..a8c7525ac 100644 --- a/src/helpers/helpers.canvas.js +++ b/src/helpers/helpers.canvas.js @@ -3,6 +3,10 @@ import {clampAll, clamp} from './helpers.core'; import {calculateTextAlignment, getSize} from './helpers.options'; const widthCache = new Map(); +const fontsKey = (fonts) => fonts.reduce(function(prev, item) { + prev += item.string; + return prev; +}, ''); /** * @typedef { import('chart.js').Point } Point @@ -77,22 +81,13 @@ export function measureLabelSize(ctx, options) { height: getSize(content.height, options.height) }; } - const font = toFont(options.font); + const optFont = options.font; + const fonts = isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)]; const strokeWidth = options.textStrokeWidth; const lines = isArray(content) ? content : [content]; - const mapKey = lines.join() + font.string + strokeWidth + (ctx._measureText ? '-spriting' : ''); + const mapKey = lines.join() + fontsKey(fonts) + strokeWidth + (ctx._measureText ? '-spriting' : ''); if (!widthCache.has(mapKey)) { - ctx.save(); - ctx.font = font.string; - const count = lines.length; - let width = 0; - for (let i = 0; i < count; i++) { - const text = lines[i]; - width = Math.max(width, ctx.measureText(text).width + strokeWidth); - } - ctx.restore(); - const height = count * font.lineHeight + strokeWidth; - widthCache.set(mapKey, {width, height}); + widthCache.set(mapKey, calculateLabelSize(ctx, lines, fonts, strokeWidth)); } return widthCache.get(mapKey); } @@ -137,19 +132,19 @@ export function drawLabel(ctx, rect, options) { return; } const labels = isArray(content) ? content : [content]; - const font = toFont(options.font); - const lh = font.lineHeight; + const optFont = options.font; + const fonts = isArray(optFont) ? optFont.map(f => toFont(f)) : [toFont(optFont)]; + const optColor = options.color; + const colors = isArray(optColor) ? optColor : [optColor]; const x = calculateTextAlignment(rect, options); - const y = rect.y + (lh / 2) + options.textStrokeWidth / 2; + const y = rect.y + options.textStrokeWidth / 2; ctx.save(); - ctx.font = font.string; ctx.textBaseline = 'middle'; ctx.textAlign = options.textAlign; if (setTextStrokeStyle(ctx, options)) { - labels.forEach((l, i) => ctx.strokeText(l, x, y + (i * lh))); + applyLabelDecoration(ctx, {x, y}, labels, fonts); } - ctx.fillStyle = options.color; - labels.forEach((l, i) => ctx.fillText(l, x, y + (i * lh))); + applyLabelContent(ctx, {x, y}, labels, {fonts, colors}); ctx.restore(); } @@ -164,6 +159,50 @@ function setTextStrokeStyle(ctx, options) { } } +function calculateLabelSize(ctx, lines, fonts, strokeWidth) { + ctx.save(); + const count = lines.length; + let width = 0; + let height = strokeWidth; + for (let i = 0; i < count; i++) { + const font = fonts[Math.min(i, fonts.length - 1)]; + ctx.font = font.string; + const text = lines[i]; + width = Math.max(width, ctx.measureText(text).width + strokeWidth); + height += font.lineHeight; + } + ctx.restore(); + return {width, height}; +} + +function applyLabelDecoration(ctx, {x, y}, labels, fonts) { + ctx.beginPath(); + let lhs = 0; + labels.forEach(function(l, i) { + const f = fonts[Math.min(i, fonts.length - 1)]; + const lh = f.lineHeight; + ctx.font = f.string; + ctx.strokeText(l, x, y + lh / 2 + lhs); + lhs += lh; + }); + ctx.stroke(); +} + +function applyLabelContent(ctx, {x, y}, labels, {fonts, colors}) { + let lhs = 0; + labels.forEach(function(l, i) { + const c = colors[Math.min(i, colors.length - 1)]; + const f = fonts[Math.min(i, fonts.length - 1)]; + const lh = f.lineHeight; + ctx.beginPath(); + ctx.font = f.string; + ctx.fillStyle = c; + ctx.fillText(l, x, y + lh / 2 + lhs); + lhs += lh; + ctx.fill(); + }); +} + function getOpacity(value, elementValue) { const opacity = isNumber(value) ? value : elementValue; return isNumber(opacity) ? clamp(opacity, 0, 1) : 1; diff --git a/test/fixtures/label/contentMultilineColors.js b/test/fixtures/label/contentMultilineColors.js new file mode 100644 index 000000000..06fe09730 --- /dev/null +++ b/test/fixtures/label/contentMultilineColors.js @@ -0,0 +1,56 @@ +module.exports = { + tolerance: 0.0150, + config: { + type: 'bar', + options: { + scales: { + x: { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + }, + y: { + display: false, + min: 0, + max: 25 + } + }, + plugins: { + annotation: { + annotations: { + text1: { + type: 'label', + xValue: 'January', + yValue: 20, + color: ['red', 'green'], + font: [{size: 24}, {size: 12}], + content: ['font: [{size: 24}, {size: 12}]', 'This is my text, row 2, longer than other', 'This is my text, row 3'], + position: { + x: 'start', + y: 'center' + }, + textAlign: 'start' + }, + text2: { + type: 'label', + xValue: 'April', + yValue: 10, + color: ['red', 'green', 'blue'], + font: [{size: 16, weight: 'bold'}, {size: 12}, {size: 8}], + content: ['font: [{size: 24, weight: bold}, {size: 12}, {size: 8}]', 'This is my text, row 2, longer than other', 'This is my text, row 3'], + }, + text3: { + type: 'label', + xValue: 'May', + yValue: 15, + color: ['blue', 'green', 'red'], + font: [{size: 12}, {size: 20, family: 'courier'}], + content: ['font: [{size: 12}, {size: 16, style: courier}],', 'This is my text, row 2'], + position: { + x: 'end' + } + }, + } + } + } + } + } +}; diff --git a/test/fixtures/label/contentMultilineColors.png b/test/fixtures/label/contentMultilineColors.png new file mode 100644 index 0000000000000000000000000000000000000000..65c1959980de5b0b30cc4623c0fb683f44ffb6a1 GIT binary patch literal 26734 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 KMNUMnLSTZ}G75nJ literal 0 HcmV?d00001 diff --git a/test/fixtures/label/contentMultilineFonts.js b/test/fixtures/label/contentMultilineFonts.js new file mode 100644 index 000000000..38ec3f11c --- /dev/null +++ b/test/fixtures/label/contentMultilineFonts.js @@ -0,0 +1,53 @@ +module.exports = { + tolerance: 0.0165, + config: { + type: 'bar', + options: { + scales: { + x: { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + }, + y: { + display: false, + min: 0, + max: 25 + } + }, + plugins: { + annotation: { + annotations: { + text1: { + type: 'label', + xValue: 'January', + yValue: 20, + font: [{size: 24}, {size: 12}], + content: ['font: [{size: 24}, {size: 12}]', 'This is my text, row 2, longer than other', 'This is my text, row 3'], + position: { + x: 'start', + y: 'center' + }, + textAlign: 'start' + }, + text2: { + type: 'label', + xValue: 'April', + yValue: 10, + font: [{size: 16, weight: 'bold'}, {size: 12}, {size: 8}], + content: ['font: [{size: 24, weight: bold}, {size: 12}, {size: 8}]', 'This is my text, row 2, longer than other', 'This is my text, row 3'], + }, + text3: { + type: 'label', + xValue: 'May', + yValue: 15, + font: [{size: 12}, {size: 20, family: 'courier'}], + content: ['font: [{size: 12}, {size: 16, style: courier}],', 'This is my text, row 2'], + position: { + x: 'end' + } + }, + } + } + } + } + } +}; diff --git a/test/fixtures/label/contentMultilineFonts.png b/test/fixtures/label/contentMultilineFonts.png new file mode 100644 index 0000000000000000000000000000000000000000..283eaf9f43714af629865e7394c2df8632c8d628 GIT binary patch literal 25554 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 z z`-8_D-Y5=1@+|Glno2niK`Fp;_IC~V-LKr8?$c7eYN@(GtQR`MtZve+?2+1+!5rFI za73?klkBMhSdt+mR%|z98*PwDLn;2DdI^x^%?k7m7Q6AgDFGYP7Qe|zDA&CB;oh4vOSxBlkI@p3crz7A> z%g=9px1a92jodd2V%jBw*{vq*(?J-W$#R2@x>OggqjZzz0C!5z8QsZ+%>DX@BVvZM zo&5li-rT1~v<8VTy-qtL5PKw~PwC_XE2_&IJz`(+R!k?QVWF~yk-j~7J26P8^jzKG z)Y7JKu6{&FF$NOdIwk#B|CPE*zVowSrzGrekX{=Kof}HFaz-(#OAzm{HbAOn%N+W# zGBkY}vnY&RBw{f{6A+n{tZMP5a=UJu%W&;+%P^t za<>HyMOE6jK75G5Vj#sn6F8vuZu`(L;XZCUf1U_geO^#=q#$QMcy{Z$@OZ?8SsopJ z_hVb=*HezH40U6(HhOb|NE*qH>D6kCf&DjkefN)>H}JVn96Az|B9$*Nt2Z2izq0tG01s}(y|q(7zrV``A|O(}Qg zuSu2n%&x3sVHZZKLD;?(NKew<{Jt>GfX=|AB0%Rl39&osVd0?Sj~|)QtgCs3)cW-IMnK>07_&DFif$eVYJw zGxJLZBtu2|Ou+$50v|xBlRIH_wDt_a^+#sPp@&EI)|?9J5S~hvNa23M&!fhyp(5U> z+;I*v-$8Ip7ZP4gL#YvrF^g+@2>J-ZKxh`ioVu`!pM|_XP#~?kdK%5 z#JFoyG6taz9a@b4b2mY9KZ{?OQ)KBhj@#qZs~VG#qdvr)gXTXJ>>KAe6FW;5b zORr?aJTaXS-CWO%eE}I*#LE?nrEd&;{>g;V86B@^dD#KX-@G1^DnhozE{cJIpL-`z z>4B_72PDl}iMW^J>M@{{ZvE8#9rG(;qzb#TOa0irA6(G%guoMKHrC`hpPtAvY+BR) z{x+AWnZERHCP>y8A3KPqEWMO_{8Q~rdy9EY5IY*(BNto~tS z{C6-i{^X;DWE=m-CDXkr13W%;_~2O&hQrAwaT@?Xln*)aL^{)1Q4ikAxqpPaf2RnB z)U@ArVKdkMkp=&kJi~fM|J`|pzXHm6m=Kk2Ylp*;!3+Ngk^ipNM&uA6VEgRgzmh$l z^_V$S1RshMHF7)j_Xkr@VrS(Gr~Xds{8&^AfP2ime9QCX@0`#92ZCe(12nad-)pUo zve&S%upqNmyV+??e{yPS$j`#!{;FEq_*%%Pr~JE9rgsO9;#*5`K}w2>J2cQYZLWAm zsYhtFx1_q{_HdFJln(CTKRtVN;Cu)n>HtXT39XgZVs^!$%sx zV=!Iwq7wc!SPQOd8XwV}F&)Ea1>zsEwr)|@UP&pasGt^9`O>jpt=9dKNUHC5Bvi`+ zF{vt})21Cjt)XbTTlGx5fg3yh0rM(_f?E#)w>U#x1z*74A%UyH^zOsoSaMasNC_1c z6*@UKHdbqa0JYJ;wC#gG#3T2(u<&j=|3k_#U+OeS&cxk+cO+~3&Yeex861Exz9;@= zgPPb#%%c45+qd~lL3v`*uizh0*InqRswgT3{(`K*!lAgaXraK;&eDW<5;RpunV`iA z3(G4{kt*WHeWFbfKDziNSk=m<_twt)fB22EJ07~Ok^M9jW(zqHwwP)*S5vLwV$0A;nkNO+Dy&HCkv zn!>JcSDOM!rc4X4`2#aSZ_{b59tX%&s7LW>^@L&lK-x+r@j>DBqcM~pCLhbieNvVx zM%|2E)^{A7U@L5nkP^se0A-4MqKSyb1qC5JFh>)U5H-4C3qO9`IJ|7X_L=jou&}U% z%lIP7&^kw8kSozNB{})xN9Bi@tp3IvlNFXtZ_2no`t#ejs~j$id#h{Z24+`HrcFWj z)OToPgshYm4`x_UsB=jkAvfnUF3Oit@&fA3v6ouDN$j2Tjr@a<}8YJxJ{ztyHM>x1J$(Z9cjJlm^nF_R!jJ zmbF|zp;q(kAk#=luITas;3CE90m}C{T=MjCr17$7Zj#*u1oE}5Q+1Xng4XD^U>1%X zkP4HARDSNB$Fy&5GPsoq*|T+atgS+Wh6hoDaJfC}RKb)^B-KX*NpqsE8=J1PX!iLh zoPR-9;fAW2)&p+KGpFz+`mNFHwu|MsLX#*p{R3)(Yu34njPjNpb6oN?1=A(L1*HBd zVR@vlrd{ICnpVcCt*yI4+7BmF>$+aS9J{8664zL~CoLdJhXd_-+WWbMrm@0wrm2v? zx`-4W#yT=%y9$9;za614VFLG9!d2E6aBW58;g8t^P2%%|0}6gAWbMEXAgg)lfZoSn zhv@r({`&@`^p`S5Simv?$M%+4eSfNe<^2}I&A4(DRYS0>ygO-; zEHZF(ZI49WX0&x)pA?p&T#mnQ_n`WUsyz2o)fSr@Y>G>Y;o?hvRW#<0WCV!hhHp6?=Y+^MviHtOa%j<+S9BmcVL9?Rks-j}`CdL=i z(#mfG-t^m_0RZm!`xyaaylh;;uPVMxy#8ixM=zm=Ksip3A0@Ktug1dWPtL*leugrY zfk5R1atT3y8CqTZ!7bPoG7D?1ShKOZ9*O)T|GNTZb^i-+xnnEMDayHGBWiFV5jG#F zPf;1&IMbXhWW8vTupaR1q4xbcnBh*Fpy`0+?*(KiCZpw=MB|9jUviz@bvlf;ZoPvR ztX7j3JfQq*SD0=f`nkoaze1FQ7TFE?sui&W`S6s$5M3V4sz>a-;-u2Iq-MU*_Zj0i z;T~}&ueS6YX06Aq7$j#$-hUh8sjK8Lw@GOMm~qD7S$T_EZvW-jjje8FZ?}zhJ=TUO zsa3bjyL}MO?^pY=d@tEDy0{JgX4f9dwz3eCTA&lceW05+H0k68-}?Gqo|@j(W~@Ab zW5^_uPfj4kr>i`?(BXqytS0i}`+1(9<{bg*klDO`^{{9k-!0!5O4#zdAc&NtxRn#! z)n8MmXyRgV88VjbS6O*vOOEHFoPd8HP^Nhsq}%d@EyZU|1X#1ut&*G96E>*7=UQ4a zQp2r1Mtc*f#+2@I(fRw#`-GpVOsxLV^}-eSAGr?eO~F_b;fkRJbl>}JZ#=&90bsG@ zxv1LrXfLT$DctRrFG9^L(JJ$>GsXKQ@@Eaxat1UCCJ`X(qfRLmYte!TYlmu2_J*j{ zeYul_wAT}}EP66i?$J9G&0NgtXDnV)woDSo8KA>6#~Z}2$+2``Pq{wLdk~s-@_KKY z9?~`tFQXQ&u9fCqSF@5VJn$|F7sN-Y>GIw>oTug{^B%fcnm@EPf#Z)>XgKu+1*@ZQ zNfR9u!^JS?_Ia+pm%RGcCKqz07RybYw$b}~wEnYiPzixPDsK{NNt?d#z)7Nsq-C^pFlf`{wN%h1YGL{10z& BD8>K) literal 0 HcmV?d00001 diff --git a/types/label.d.ts b/types/label.d.ts index c5cc688e3..4c66511f2 100644 --- a/types/label.d.ts +++ b/types/label.d.ts @@ -39,8 +39,8 @@ export interface CalloutOptions { export interface CoreLabelOptions { drawTime?: Scriptable, - font?: Scriptable, PartialEventContext>, - color?: Scriptable, + font?: Scriptable | Partial[], PartialEventContext>, + color?: Scriptable, /** * Padding of label * @default 6