diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index d05fe0ca8..c2291d63e 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -73,7 +73,7 @@ The `init` option is scriptable but it doesn't get the [options context](./optio This is the signature of the scriptable option: ```javascript -({chart, properties, options}) => void | boolean | AnnotationBoxModel +({chart, properties, options}) => void | boolean | AnnotationElement ``` where the properties is the element model diff --git a/src/helpers/helpers.chart.js b/src/helpers/helpers.chart.js index 0d976604d..76ab085c6 100644 --- a/src/helpers/helpers.chart.js +++ b/src/helpers/helpers.chart.js @@ -177,9 +177,9 @@ export function resolveLineProperties(chart, options) { * @param {boolean} [centerBased=false] * @returns {AnnotationBoxModel} */ -export function resolveBoxAndLabelProperties(chart, options, centerBased) { +export function resolveBoxAndLabelProperties(chart, options) { const properties = resolveBoxProperties(chart, options); - properties.initProperties = initAnimationProperties(chart, properties, options, centerBased); + properties.initProperties = initAnimationProperties(chart, properties, options); properties.elements = [{ type: 'label', optionScope: 'label', diff --git a/src/helpers/helpers.options.js b/src/helpers/helpers.options.js index 8fffd084d..f0e7f0225 100644 --- a/src/helpers/helpers.options.js +++ b/src/helpers/helpers.options.js @@ -1,13 +1,24 @@ -import {isObject, isFunction, valueOrDefault, defined, callback} from 'chart.js/helpers'; +import {isObject, isFunction, valueOrDefault, defined, callback as invoke} from 'chart.js/helpers'; import {clamp} from './helpers.core'; const isPercentString = (s) => typeof s === 'string' && s.endsWith('%'); const toPercent = (s) => parseFloat(s) / 100; const toPositivePercent = (s) => clamp(toPercent(s), 0, 1); +const boxAppering = (x, y) => ({x, y, x2: x, y2: y, width: 0, height: 0}); +const defaultInitAnimation = { + box: (properties) => boxAppering(properties.centerX, properties.centerY), + ellipse: (properties) => ({centerX: properties.centerX, centerY: properties.centerX, radius: 0, width: 0, height: 0}), + label: (properties) => boxAppering(properties.centerX, properties.centerY), + line: (properties) => boxAppering(properties.x, properties.y), + point: (properties) => ({centerX: properties.centerX, centerY: properties.centerY, radius: 0, width: 0, height: 0}), + polygon: (properties) => boxAppering(properties.centerX, properties.centerY) +}; + /** * @typedef { import("chart.js").Chart } Chart * @typedef { import('../../types/element').AnnotationBoxModel } AnnotationBoxModel + * @typedef { import('../../types/element').AnnotationElement } AnnotationElement * @typedef { import('../../types/options').AnnotationPointCoordinates } AnnotationPointCoordinates * @typedef { import('../../types/label').CoreLabelOptions } CoreLabelOptions * @typedef { import('../../types/label').LabelPositionObject } LabelPositionObject @@ -93,17 +104,16 @@ export function isBoundToPoint(options) { * @param {Chart} chart * @param {AnnotationBoxModel} properties * @param {CoreAnnotationOptions} options - * @param {boolean} [centerBased=false] - * @returns {AnnotationBoxModel} + * @returns {AnnotationElement} */ -export function initAnimationProperties(chart, properties, options, centerBased = false) { +export function initAnimationProperties(chart, properties, options) { const initAnim = options.init; if (!initAnim) { return; } else if (initAnim === true) { - return applyDefault(properties, centerBased); + return applyDefault(properties, options); } - return checkCallbackResult(properties, centerBased, callback(initAnim, [{chart, properties, options}])); + return execCallback(chart, properties, options); } /** @@ -125,16 +135,15 @@ export function loadHooks(options, hooks, hooksContainer) { return activated; } -function applyDefault({centerX, centerY}, centerBased) { - if (centerBased) { - return {centerX, centerY, radius: 0, width: 0, height: 0}; - } - return {x: centerX, y: centerY, x2: centerX, y2: centerY, width: 0, height: 0}; +function applyDefault(properties, options) { + const type = options.type || 'line'; + return defaultInitAnimation[type](properties); } -function checkCallbackResult(properties, centerBased, result) { +function execCallback(chart, properties, options) { + const result = invoke(options.init, [{chart, properties, options}]); if (result === true) { - return applyDefault(properties, centerBased); + return applyDefault(properties, options); } else if (isObject(result)) { return result; } diff --git a/src/types/ellipse.js b/src/types/ellipse.js index 0721f1ee2..bddb9511f 100644 --- a/src/types/ellipse.js +++ b/src/types/ellipse.js @@ -44,7 +44,7 @@ export default class EllipseAnnotation extends Element { } resolveElementProperties(chart, options) { - return resolveBoxAndLabelProperties(chart, options, true); + return resolveBoxAndLabelProperties(chart, options); } } diff --git a/src/types/point.js b/src/types/point.js index 696ddf4d8..8fd9549d6 100644 --- a/src/types/point.js +++ b/src/types/point.js @@ -39,7 +39,7 @@ export default class PointAnnotation extends Element { resolveElementProperties(chart, options) { const properties = resolvePointProperties(chart, options); - properties.initProperties = initAnimationProperties(chart, properties, options, true); + properties.initProperties = initAnimationProperties(chart, properties, options); return properties; } } diff --git a/test/specs/animation.spec.js b/test/specs/animation.spec.js index 7d2bb4e0c..669672d7d 100644 --- a/test/specs/animation.spec.js +++ b/test/specs/animation.spec.js @@ -4,7 +4,7 @@ describe('Initial animation', function() { box: 'x', ellipse: 'width', label: 'x', - line: 'x', + line: 'x2', point: 'radius', polygon: 'y' }; diff --git a/types/options.d.ts b/types/options.d.ts index 0d6ae8f36..c36c55fd4 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -1,7 +1,7 @@ import { Chart, Color, PointStyle, BorderRadius, CoreInteractionOptions } from 'chart.js'; import { AnnotationEvents, PartialEventContext, EventContext } from './events'; import { LabelOptions, BoxLabelOptions, LabelTypeOptions } from './label'; -import { AnnotationBoxModel } from './element'; +import { AnnotationBoxModel, AnnotationElement } from './element'; export type DrawTime = 'afterDraw' | 'afterDatasetsDraw' | 'beforeDraw' | 'beforeDatasetsDraw'; @@ -42,7 +42,7 @@ export interface CoreAnnotationOptions extends AnnotationEvents, ShadowOptions, borderWidth?: Scriptable, display?: Scriptable, drawTime?: Scriptable, - init?: boolean | ((chart: Chart, properties: AnnotationBoxModel, options: AnnotationOptions) => void | boolean | AnnotationBoxModel), + init?: boolean | ((chart: Chart, properties: AnnotationBoxModel, options: AnnotationOptions) => void | boolean | AnnotationElement), id?: string, xMax?: Scriptable, xMin?: Scriptable,