fix: better animation

This commit is contained in:
Fredrik Burmester
2026-01-06 15:37:13 +01:00
parent 4bdb8003bb
commit a24e254a9e

View File

@@ -1,5 +1,14 @@
import React, { useEffect, useRef } from "react";
import { Animated, Easing, View } from "react-native";
import React, { useEffect } from "react";
import { View } from "react-native";
import Animated, {
Easing,
interpolate,
useAnimatedStyle,
useSharedValue,
withDelay,
withRepeat,
withTiming,
} from "react-native-reanimated";
interface Props {
color?: string;
@@ -9,6 +18,54 @@ interface Props {
gap?: number;
}
const MIN_SCALE = 0.35;
const MAX_SCALE = 1;
const DURATIONS = [800, 650, 750];
const DELAYS = [0, 200, 100];
const Bar: React.FC<{
color: string;
barWidth: number;
height: number;
duration: number;
delay: number;
}> = ({ color, barWidth, height, duration, delay }) => {
const progress = useSharedValue(0);
useEffect(() => {
progress.value = withDelay(
delay,
withRepeat(
withTiming(1, { duration, easing: Easing.inOut(Easing.ease) }),
-1,
true,
),
);
}, []);
const animatedStyle = useAnimatedStyle(() => ({
transform: [
{
scaleY: interpolate(progress.value, [0, 1], [MIN_SCALE, MAX_SCALE]),
},
],
}));
return (
<Animated.View
style={[
{
width: barWidth,
height,
backgroundColor: color,
borderRadius: 1,
},
animatedStyle,
]}
/>
);
};
export const AnimatedEqualizer: React.FC<Props> = ({
color = "#9334E9",
barWidth = 3,
@@ -16,48 +73,6 @@ export const AnimatedEqualizer: React.FC<Props> = ({
height = 12,
gap = 2,
}) => {
const animations = useRef(
Array.from({ length: barCount }, () => new Animated.Value(0)),
).current;
useEffect(() => {
const durations = [600, 700, 550];
const minScale = [0.2, 0.3, 0.25];
const maxScale = [1, 0.85, 0.95];
// Set initial staggered values
animations.forEach((anim, index) => {
anim.setValue(index === 1 ? 0.8 : index === 2 ? 0.4 : 0.2);
});
const barAnimations = animations.map((anim, index) => {
return Animated.loop(
Animated.sequence([
Animated.timing(anim, {
toValue: maxScale[index % maxScale.length],
duration: durations[index % durations.length],
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
Animated.timing(anim, {
toValue: minScale[index % minScale.length],
duration: durations[index % durations.length],
easing: Easing.inOut(Easing.ease),
useNativeDriver: true,
}),
]),
);
});
Animated.parallel(barAnimations).start();
return () => {
animations.forEach((anim) => {
anim.stopAnimation();
});
};
}, [animations]);
return (
<View
style={{
@@ -68,16 +83,14 @@ export const AnimatedEqualizer: React.FC<Props> = ({
marginRight: 6,
}}
>
{animations.map((anim, index) => (
<Animated.View
{Array.from({ length: barCount }).map((_, index) => (
<Bar
key={index}
style={{
width: barWidth,
height,
backgroundColor: color,
borderRadius: 1,
transform: [{ scaleY: anim }],
}}
color={color}
barWidth={barWidth}
height={height}
duration={DURATIONS[index % DURATIONS.length]}
delay={DELAYS[index % DELAYS.length]}
/>
))}
</View>