animation handler

This commit is contained in:
Nate Kelley 2025-04-02 16:20:48 -06:00
parent 0f5648c2c8
commit 26db7bb1df
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
6 changed files with 80 additions and 15 deletions

View File

@ -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;

View File

@ -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'];
};

View File

@ -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;

View File

@ -1,5 +0,0 @@
import { AnimationSpec } from 'chart.js';
export interface CustomAnimationSpec extends AnimationSpec<'doughnut' | 'pie'> {
onProgress?: (animation: { currentStep: number; numSteps: number }) => void;
}

View File

@ -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<ChartTypeJS>['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<ChartType, () => AnimationOptions<ChartTypeJS>['animation']> = {
bar: barDelayAnimation,
line: () => ({}),
scatter: () => ({}),
pie: () => ({}),
metric: () => ({}),
table: () => ({}),
combo: () => ({})
};

View File

@ -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;