Mobile | Thu May 01 20250 views
Particles Animation
Hi there! 👋
I needed an animation for an app I'm working on, so I went to bolt.new and ask the AI to generate a reaction animation. And it was a success!
In case you need a similar animation, you can use the code below.
How to use
Here's an example of how to use the animation:
import { useState } from "react";
import { View, Button } from "react-native";
import ReactionParticles from "./ReactionParticles";
const reactionColors = ["#FF7E7E", "#7EB3FF", "#8FD28F", "#FFE07E", "#D7A0FF"];
export default function ReactionAnimation() {
const [activeParticle, setActiveParticle] = useState<boolean>(false);
function handleShowParticles() {
setActiveParticle(true);
setTimeout(() => {
setActiveParticle(false);
}, 1000);
return (
<View>
{activeParticle && (
<ReactionParticles
color={
reactionColors[Math.floor(Math.random() * reactionColors.length)]
}
/>
)}
<Button onPress={handleShowParticles}>Show Particles</Button>
</View>
);
}
}
Simple as that! Just pass the color you want to use and the animation will be shown. We use a timeout to hide the animation after 1 second.
ReactionParticles Component
You can copy paste the code below to use the animation in your project. Just make sure you have react-native-reanimated
installed.
import { useEffect } from "react";
import { View, StyleSheet } from "react-native";
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withDelay,
Easing,
} from "react-native-reanimated";
interface ParticleProps {
color: string;
delay: number;
x: number;
y: number;
size: number;
}
function Particle({ color, delay, x, y, size }: ParticleProps) {
const opacity = useSharedValue(0);
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const scale = useSharedValue(0);
useEffect(() => {
// Start animation
opacity.value = withDelay(delay, withTiming(1, { duration: 200 }));
scale.value = withDelay(delay, withTiming(1, { duration: 300 }));
translateX.value = withDelay(
delay,
withTiming(x, {
duration: 500,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
}),
);
translateY.value = withDelay(
delay,
withTiming(y, {
duration: 500,
easing: Easing.bezier(0.25, 0.1, 0.25, 1),
}),
);
// Fade out
const timerId = setTimeout(() => {
opacity.value = withTiming(0, { duration: 300 });
scale.value = withTiming(0.5, { duration: 300 });
}, delay + 300);
return () => clearTimeout(timerId);
}, []);
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: opacity.value,
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value },
{ scale: scale.value },
],
};
});
return (
<Animated.View
style={[
styles.particle,
{ backgroundColor: color, width: size, height: size },
animatedStyle,
]}
/>
);
}
interface ReactionParticlesProps {
color: string;
}
export function ReactionParticles({ color }: ReactionParticlesProps) {
// Create particles in different directions
const particles = Array.from({ length: 8 }).map((_, i) => {
const angle = (i / 8) * Math.PI * 2;
const distance = 25 + Math.random() * 10;
return {
id: i,
color,
delay: Math.random() * 100,
x: Math.cos(angle) * distance,
y: Math.sin(angle) * distance,
size: 5 + Math.random() * 4,
};
});
return (
<View style={styles.container}>
{particles.map((particle) => (
<Particle
key={particle.id}
color={particle.color}
delay={particle.delay}
x={particle.x}
y={particle.y}
size={particle.size}
/>
))}
</View>
);
}
const styles = StyleSheet.create({
container: {
position: "absolute",
width: 40,
height: 40,
justifyContent: "center",
alignItems: "center",
zIndex: 10,
},
particle: {
position: "absolute",
borderRadius: 100,
},
});
Stay tuned! 🔌
Create an account to get our newsletter with updates, tips, and exclusive content — delivered straight to your inbox. Just hit the Sign Up button in the top right to get started.