diff --git a/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts b/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts index a90a756eb..c53e4df6e 100644 --- a/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts +++ b/web/src/components/ui/charts/BusterChartJS/ChartJSTheme.ts @@ -24,7 +24,6 @@ import { scales } from 'chart.js'; import { ChartMountedPlugin } from './core/plugins'; -import CrosshairPlugin from './core/plugins/chartjs-plugin-crosshair'; import ChartDeferred from 'chartjs-plugin-deferred'; import ChartJsAnnotationPlugin from 'chartjs-plugin-annotation'; import ChartDataLabels from 'chartjs-plugin-datalabels'; @@ -70,8 +69,7 @@ ChartJS.register( LogarithmicScale, TimeScale, TimeSeriesScale, - ChartDataLabels, - CrosshairPlugin + ChartDataLabels ); ChartJS.defaults.responsive = true; diff --git a/web/src/components/ui/charts/BusterChartJS/core/animations/barDelayAnimation.ts b/web/src/components/ui/charts/BusterChartJS/core/animations/barDelayAnimation.ts new file mode 100644 index 000000000..3e2e164dd --- /dev/null +++ b/web/src/components/ui/charts/BusterChartJS/core/animations/barDelayAnimation.ts @@ -0,0 +1,23 @@ +import { AnimationOptions, AnimationSpec } from 'chart.js'; + +export const barDelayAnimation = (props?: { dataDelay?: number; datasetDelay?: number }) => { + const { dataDelay = 200, datasetDelay = 100 } = props || {}; + let delayed = false; + return { + onComplete: () => { + delayed = true; + }, + delay: (context) => { + let delay = 0; + const numberOfDatasets = context.chart.data.datasets.length; + const numberOfDataPoints = context.chart.data.datasets[context.datasetIndex].data.length; + + if (context.type === 'data' && context.mode === 'default' && !delayed) { + delay = context.dataIndex * dataDelay + context.datasetIndex * datasetDelay; + // Ensure the maximum delay is 1000ms + delay = Math.min(delay, 1000); + } + return delay; + } + } satisfies AnimationOptions<'bar'>['animation']; +}; diff --git a/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-pie-outlabels/plugin.ts b/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-pie-outlabels/plugin.ts index ab59247a9..90784c65d 100644 --- a/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-pie-outlabels/plugin.ts +++ b/web/src/components/ui/charts/BusterChartJS/core/plugins/chartjs-plugin-pie-outlabels/plugin.ts @@ -1,10 +1,21 @@ -import { ArcElement, Chart, ChartDataset, ChartMeta, ChartType, Plugin } from 'chart.js'; +import { + AnimationSpec, + ArcElement, + Chart, + ChartDataset, + ChartMeta, + ChartType, + Plugin +} from 'chart.js'; import OutLabel from './OutLabel'; import OutLabelsContext from './OutLabelsContext'; import OutLabelsManager from './OutLabelsManager'; import { OutLabelStyle } from './OutLabelsStyle'; import { OutLabelsOptions } from './OutLabelsOptions'; -import { CustomAnimationSpec } from '../common'; + +interface CustomAnimationSpec extends AnimationSpec<'doughnut' | 'pie'> { + onProgress?: (animation: { currentStep: number; numSteps: number }) => void; +} const globalAnimationDuration = (Chart.defaults.animation as CustomAnimationSpec).duration; diff --git a/web/src/components/ui/charts/BusterChartJS/core/plugins/common.ts b/web/src/components/ui/charts/BusterChartJS/core/plugins/common.ts deleted file mode 100644 index d7662a075..000000000 --- a/web/src/components/ui/charts/BusterChartJS/core/plugins/common.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { AnimationSpec } from 'chart.js'; - -export interface CustomAnimationSpec extends AnimationSpec<'doughnut' | 'pie'> { - onProgress?: (animation: { currentStep: number; numSteps: number }) => void; -} diff --git a/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useAnimations.ts b/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useAnimations.ts new file mode 100644 index 000000000..9618bb149 --- /dev/null +++ b/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useAnimations.ts @@ -0,0 +1,38 @@ +import { useMemo } from 'react'; +import { barDelayAnimation } from '../../core/animations/barDelayAnimation'; +import { ANIMATION_DURATION, ANIMATION_THRESHOLD } from '../../../config'; +import { AnimationOptions, ChartType as ChartTypeJS } from 'chart.js'; +import { ChartType } from '@/api/asset_interfaces/metric'; + +export const useAnimations = ({ + animate, + numberOfSources, + chartType +}: { + animate: boolean; + numberOfSources: number; + chartType: ChartType; +}): AnimationOptions['animation'] => { + const isAnimationEnabled = useMemo(() => { + return animate && numberOfSources <= ANIMATION_THRESHOLD; + }, [animate, numberOfSources]); + + return useMemo(() => { + return isAnimationEnabled + ? { + duration: ANIMATION_DURATION, + ...animationRecord[chartType]?.() + } + : false; + }, [isAnimationEnabled, chartType]); +}; + +const animationRecord: Record AnimationOptions['animation']> = { + bar: barDelayAnimation, + line: () => ({}), + scatter: () => ({}), + pie: () => ({}), + metric: () => ({}), + table: () => ({}), + combo: () => ({}) +}; diff --git a/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useOptions.tsx b/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useOptions.tsx index 450958a1e..53b1b04b8 100644 --- a/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useOptions.tsx +++ b/web/src/components/ui/charts/BusterChartJS/hooks/useOptions/useOptions.tsx @@ -23,6 +23,8 @@ import { LINE_DECIMATION_THRESHOLD, TOOLTIP_THRESHOLD } from '../../../config'; +import { barDelayAnimation } from '../../core/animations/barDelayAnimation'; +import { useAnimations } from './useAnimations'; interface UseOptionsProps { colors: string[]; @@ -173,9 +175,7 @@ export const useOptions = ({ }, 0); }, [datasetOptions]); - const isAnimationEnabled = useMemo(() => { - return animate && numberOfSources <= ANIMATION_THRESHOLD; - }, [animate, numberOfSources]); + const animation = useAnimations({ animate, numberOfSources, chartType: selectedChartType }); const disableTooltip = useMemo(() => { return disableTooltipProp || numberOfSources >= TOOLTIP_THRESHOLD; @@ -202,7 +202,7 @@ export const useOptions = ({ return { indexAxis: isHorizontalBar ? 'y' : 'x', - animation: isAnimationEnabled ? { duration: ANIMATION_DURATION } : false, + animation, backgroundColor: colors, borderColor: colors, scales, @@ -236,7 +236,7 @@ export const useOptions = ({ goalLinesAnnotations, trendlineAnnotations, tooltipOptions, - isAnimationEnabled + animate ]); return options;