Introduction
Today, we’ll explore how to create a spectacular coin celebration effect, similar to winning celebrations in casino games. This effect includes coins bursting outward and flying to a target point, accompanied by light effects and a backdrop animation.
Try to dive into the deep research demo on Playground
Technologies Used
- ReactJS: UI and state management
- Framer Motion: Smooth animations
- TailwindCSS: Styling
- Lodash: Utility functions
Prerequisites
- Basic understanding of React Hooks (useState, useEffect)
- Familiarity with TailwindCSS
- Basic knowledge of animations and transforms
Component Analysis
1. Particle System
const ParticleSystem = ({ totalParticles, animatedCount, isActive, gcRef, onFirstCoinReachTarget }) => {
// ... code
}
Main component managing the entire particle system. Props:
totalParticles
: Total number of coinsanimatedCount
: Number of animated coinsgcRef
: References to target pointsonFirstCoinReachTarget
: Callback when first coin reaches target
2. Animation Structure
a. Backdrop Effect
<motion.div
className="fixed inset-0 bg-black/90 z-10"
initial={{ opacity: 0 }}
animate={{
opacity: isVisibleGC ? 0.9 : 0,
display: isVisibleGC ? "block" : "none"
}}
transition={{
duration: 0.2,
ease: "easeInOut"
}}
/>
- Creates a dark background with 0.9 opacity
- Smooth fade in/out animation
b. Particle Animation
const calculateExplosionPath = (position, index, total) => {
// Calculate particle path
return {
initial: { x: 0, y: 0, scale: 0.1 },
explosion: { x: explosionX, y: explosionY, scale: 0.7 },
collection: { x: locationX, y: locationY, scale: 0.3 }
};
};
Animation divided into three phases:
- Initial: Starting position
- Explosion: Burst outward
- Collection: Flying to target
3. Animation Techniques
a. Sequence Player
const Particle = ({ frames, isAnimated }) => {
const [currentFrame, setCurrentFrame] = useState(() =>
Math.floor(random() * frames.length - 10)
);
useEffect(() => {
if (isAnimated) {
const interval = setInterval(() => {
setCurrentFrame(prev => (prev + 1) % frames.length);
}, 40);
return () => clearInterval(interval);
}
}, [isAnimated, frames.length]);
return <motion.img src={frames[currentFrame]} alt="particle" />;
};
- Creates animation by switching frames
- 40ms interval for 25fps
- Random start frame for variety
b. Timing Control
const timing = {
delay: index * 0.015, // Delay between coins
duration: 1.5 // Flight duration
};
- Incremental delay creates sequential effect
- Duration controls flight speed
Tips and Tricks
- Performance Optimization
// Use React.memo to prevent unnecessary re-renders
const Particle = React.memo(({ frames, isAnimated }) => {
// ... code
});
- Dynamic Positioning
const getCircularPosition = (innerRadius, outerRadius) => {
const angle = random() * Math.PI;
const r = Math.sqrt(random() * (outerRadius ** 2 - innerRadius ** 2) + innerRadius ** 2);
return {
x: r * Math.cos(angle),
y: r * Math.sin(angle)
};
};
- Generates random positions in a circle
- Ensures even distribution
- Cleanup
useEffect(() => {
let mounted = true;
let timeouts = [];
// ... code
return () => {
mounted = false;
timeouts.forEach(clearTimeout);
};
}, [isActive]);
- Cleans up timeouts to prevent memory leaks
- Checks mounted state before updates
Conclusion
This effect combines multiple techniques:
- Particle systems
- Frame-based animation
- Motion transitions
- Dynamic positioning
- Timing control
For smooth effects, remember to:
- Synchronize animation timings
- Properly clean up resources
- Optimize performance with React.memo
- Use Framer Motion for complex animations
Further Learning Resources
- Framer Motion Documentation
- React Performance Optimization
- TailwindCSS
- JavaScript Animation Best Practices
This article helps you understand how to build a complex effect from basic concepts. Experiment and create your own variations!
Bonus Tips
- Use
transform
instead of position properties for better performance - Implement progressive enhancement for slower devices
- Consider adding sound effects for more impact
- Test on different screen sizes and devices
- Use
requestAnimationFrame
for smooth animations - Consider adding error boundaries for robustness
Remember, great animations enhance user experience but should never interfere with functionality. Always prioritize performance and accessibility in your implementations.