From edfd632ff1c74be80d42416ea1b5097de665e366 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 24 Apr 2024 12:30:20 +0200 Subject: [PATCH 1/5] [charts] Fix line animation --- .../x-charts/src/internals/useAnimatedPath.ts | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/packages/x-charts/src/internals/useAnimatedPath.ts b/packages/x-charts/src/internals/useAnimatedPath.ts index 034302c08f7b..c7eceeaf62e4 100644 --- a/packages/x-charts/src/internals/useAnimatedPath.ts +++ b/packages/x-charts/src/internals/useAnimatedPath.ts @@ -1,29 +1,40 @@ import * as React from 'react'; import { interpolateString } from 'd3-interpolate'; -import { useSpring, to } from '@react-spring/web'; - -function usePrevious(value: T) { - const ref = React.useRef(null); - React.useEffect(() => { - ref.current = value; - }, [value]); - return ref.current; -} +import { useSpringRef, useSpring, to } from '@react-spring/web'; // Taken from Nivo export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { - const previousPath = usePrevious(path); - const interpolator = React.useMemo( - () => (previousPath ? interpolateString(previousPath, path) : () => path), - [previousPath, path], - ); + const previousPathRef = React.useRef(null); + const currentPathRef = React.useRef(path); + + const api = useSpringRef(); + + React.useEffect(() => { + if (previousPathRef.current !== path) { + // Only start the animation if the previouse path is different. + // Avoid re-animating if the props is updated with the same value.u + api.start(); + } + if (currentPathRef.current !== path) { + previousPathRef.current = currentPathRef.current; + currentPathRef.current = path; + } + }, [api, path]); const { value } = useSpring({ + ref: api, from: { value: 0 }, to: { value: 1 }, reset: true, immediate: skipAnimation, }); - return to([value], interpolator); + const interpolation = (t: number) => { + if (previousPathRef.current === null) { + return path; + } + return interpolateString(previousPathRef.current, path)(t); + }; + + return to([value], interpolation); }; From c4239a6d03df1d308309de1f45cbac144137407d Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 24 Apr 2024 14:43:27 +0200 Subject: [PATCH 2/5] fix resolved animation --- packages/x-charts/src/internals/useAnimatedPath.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/x-charts/src/internals/useAnimatedPath.ts b/packages/x-charts/src/internals/useAnimatedPath.ts index c7eceeaf62e4..ea4c9dced212 100644 --- a/packages/x-charts/src/internals/useAnimatedPath.ts +++ b/packages/x-charts/src/internals/useAnimatedPath.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { interpolateString } from 'd3-interpolate'; -import { useSpringRef, useSpring, to } from '@react-spring/web'; +import { useSpringRef, useSpring } from '@react-spring/web'; // Taken from Nivo export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { @@ -21,12 +21,16 @@ export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { } }, [api, path]); - const { value } = useSpring({ + const spring = useSpring({ ref: api, from: { value: 0 }, to: { value: 1 }, reset: true, immediate: skipAnimation, + onResolve() { + previousPathRef.current = path; + currentPathRef.current = path; + }, }); const interpolation = (t: number) => { @@ -35,6 +39,5 @@ export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { } return interpolateString(previousPathRef.current, path)(t); }; - - return to([value], interpolation); + return spring.value.to(interpolation); }; From c31d7e030234d10898180280cb6290a8d1037159 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 24 Apr 2024 14:51:41 +0200 Subject: [PATCH 3/5] keep memo --- packages/x-charts/src/internals/useAnimatedPath.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/x-charts/src/internals/useAnimatedPath.ts b/packages/x-charts/src/internals/useAnimatedPath.ts index ea4c9dced212..b8e09a118056 100644 --- a/packages/x-charts/src/internals/useAnimatedPath.ts +++ b/packages/x-charts/src/internals/useAnimatedPath.ts @@ -33,11 +33,12 @@ export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { }, }); - const interpolation = (t: number) => { + const interpolation = React.useMemo(() => { if (previousPathRef.current === null) { - return path; + return () => path; } - return interpolateString(previousPathRef.current, path)(t); - }; + return interpolateString(previousPathRef.current, path); + }, [path]); + return spring.value.to(interpolation); }; From 1fd1cacd5f17a3aacf147f4907870f46cc120fc1 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 24 Apr 2024 15:25:13 +0200 Subject: [PATCH 4/5] tiny improvement --- packages/x-charts/src/internals/useAnimatedPath.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/x-charts/src/internals/useAnimatedPath.ts b/packages/x-charts/src/internals/useAnimatedPath.ts index b8e09a118056..ea60e78b8869 100644 --- a/packages/x-charts/src/internals/useAnimatedPath.ts +++ b/packages/x-charts/src/internals/useAnimatedPath.ts @@ -12,13 +12,12 @@ export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { React.useEffect(() => { if (previousPathRef.current !== path) { // Only start the animation if the previouse path is different. - // Avoid re-animating if the props is updated with the same value.u + // Avoid re-animating if the props is updated with the same value. api.start(); } - if (currentPathRef.current !== path) { - previousPathRef.current = currentPathRef.current; - currentPathRef.current = path; - } + + previousPathRef.current = currentPathRef.current; + currentPathRef.current = path; }, [api, path]); const spring = useSpring({ From 17abb38aa3e7b43a67e6bf3a89566c26d63be233 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 24 Apr 2024 16:03:10 +0200 Subject: [PATCH 5/5] ximplify the modification --- packages/x-charts/src/internals/useAnimatedPath.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/x-charts/src/internals/useAnimatedPath.ts b/packages/x-charts/src/internals/useAnimatedPath.ts index ea60e78b8869..bdede9ca3126 100644 --- a/packages/x-charts/src/internals/useAnimatedPath.ts +++ b/packages/x-charts/src/internals/useAnimatedPath.ts @@ -1,27 +1,18 @@ import * as React from 'react'; import { interpolateString } from 'd3-interpolate'; -import { useSpringRef, useSpring } from '@react-spring/web'; +import { useSpring } from '@react-spring/web'; // Taken from Nivo export const useAnimatedPath = (path: string, skipAnimation?: boolean) => { const previousPathRef = React.useRef(null); const currentPathRef = React.useRef(path); - const api = useSpringRef(); - React.useEffect(() => { - if (previousPathRef.current !== path) { - // Only start the animation if the previouse path is different. - // Avoid re-animating if the props is updated with the same value. - api.start(); - } - previousPathRef.current = currentPathRef.current; currentPathRef.current = path; - }, [api, path]); + }, [path]); const spring = useSpring({ - ref: api, from: { value: 0 }, to: { value: 1 }, reset: true,