Bursting Colourful Crackers With react-native-fireworks
An npm package to burst crackers in your React native app.
Author

Date

Book a call
Hey there!
Ever felt a need to burst colourful fireworks ? in your mobile app, like when there’s something to celebrate? Here’s an npm package I created for that.
To use it in your React Native project, you can install it from https://www.npmjs.com/package/react-native-fireworks.
Using it as a component is as simple as -
import Fireworks from 'react-native-fireworks';
...
<Fireworks/>This component accepts a total of 8 props, all of which are optional. Below is a demonstration that uses all the 8 props-
<Fireworks
speed={3}
density={8}
colors={['#ff0','#ff3','#cc0','#ff4500','#ff6347']}
iterations={5}
height={150}
width={100}
zIndex={2}
circular={true}
/>Behind the scenes
This is my first package on npm. I created it using Animated class that comes with React Native. For creating firework-like objects, I designed colourful circles of small radii moving in all the directions randomly and fading away.
So basically, a single firecracker consists of some 30 small circles of different colours. These circles are initially positioned at the centre of a square of width 200.
Step 1. Drawing a single firecracker ?
We begin with a square box that will contain the colourful light balls:
<View style={styles.explosionBoundary}>
{/*<code to draw the light balls>*/}
</View>The box with style explosionBoundary has a fixed height and width of 200 each. The coloured light balls will move within this boundary.
const styles = StyleSheet.create({
explosionBoundary: {
position: 'absolute',
height: 200,
width: 200,
},
});Next, we draw some balls, say 30 balls, and fill them with random colours. These balls are positioned at the centre of the square box that we made above.
class Fireworks extends Component {
getRandom = (n) => {
return Math.round(Math.random() * n);
};
render(){
let balls = [],
randomColors = [];
for (let i = 0; i < 30; i++) {
balls.push('');
randomColors[i] =
'rgb(' +
this.getRandom(255) +
',' +
this.getRandom(255) +
',' +
this.getRandom(255) +
')';
}
return(
<View style={styles.explosionBoundary}>
{balls.map((ball, index) => {
return (
<View
style={[
styles.ball,
{
top: 100,
left: 100,
backgroundColor: randomColors[index],
},
]}
/>
);
})}
</View>);
}
}
const styles = StyleSheet.create({
explosionBoundary: {
position: 'absolute',
height: 200,
width: 200,
},
ball: {
position: 'absolute',
height: 7,
width: 7,
borderRadius: 3,
},
});At this point, we can only see a small circle because all the balls are positioned at the same point and they all overlap. So, we need to move them in different directions to be able to see them.
Step 2. Bursting the cracker ?
To move the balls we will use Animated class from React Native. We start by creating two variables that will control the opacity and position of the light balls.
this.fadingOpacity = new Animated.Value(1);
this.movingBall = new Animated.Value(0);Now we use Animated.timing with these variables and create functions that will actually animate the objects.
animateOpacity() {
this.fadingOpacity.setValue(1);
Animated.timing(this.fadingOpacity, {
toValue: 0,
duration: 700,
easing: Easing.ease,
useNativeDriver: false,
}).start();
}
animateBall() {
this.movingBall.setValue(0);
Animated.timing(this.movingBall, {
toValue: 1,
duration: 700,
easing: Easing.ease,
useNativeDriver: false,
}).start();
}We use the variables this.fadingOpacity and this.movingBall to move the balls in all the directions and fade them simultaneously. At this point, our code looks like:
import React from 'react';
import { StyleSheet, View, Animated, Easing } from 'react-native';
export default class Fireworks extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
x: [],
y: [],
};
this.fadingOpacity = new Animated.Value(1);
this.movingBall = new Animated.Value(0);
}
componentDidMount() {
this.animateOpacity();
this.animateBall();
}
getRandom = (n) => {
return Math.round(Math.random() * n);
};
animateOpacity() {
this.fadingOpacity.setValue(1);
Animated.timing(this.fadingOpacity, {
toValue: 0,
duration: 700,
easing: Easing.ease,
useNativeDriver: false,
}).start(() => this.animateOpacity());
}
animateBall() {
this.movingBall.setValue(0);
Animated.timing(this.movingBall, {
toValue: 1,
duration: 700,
easing: Easing.ease,
useNativeDriver: false,
}).start(() => this.animateBall());
}
render() {
let balls = [],
randomTops = [],
randomLefts = [],
randomColors = [];
for (let i = 0; i < 30; i++) {
balls.push('');
randomTops[i] = this.movingBall.interpolate({
inputRange: [0, 1],
outputRange: [100, this.getRandom(200)],
});
randomLefts[i] = this.movingBall.interpolate({
inputRange: [0, 1],
outputRange: [100, this.getRandom(200)],
});
randomColors[i] =
'rgb(' +
this.getRandom(255) +
',' +
this.getRandom(255) +
',' +
this.getRandom(255) +
')';
}
let ballOpacity = this.fadingOpacity.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
return (
<View style={styles.explosionBoundary}>
{balls.map((ball, index) => {
return (
<Animated.View
style={[
styles.ball,
{
top: randomTops[index],
left: randomLefts[index],
opacity: ballOpacity,
backgroundColor: randomColors[index],
},
]}
/>
);
})}
</View>);
}
}
const styles = StyleSheet.create({
explosionBoundary: {
position: 'absolute',
height: 200,
width: 200,
},
ball: {
position: 'absolute',
height: 7,
width: 7,
borderRadius: 3,
},
});The above code is enough to burst a single firecracker, and here it does!

Notice that the initial positions- top and left of all the balls are the same, i.e. 100, but the final positions are randomly set. So the distances travelled by each ball will be different. Also, the time taken by each ball to move from the initial position to the final position is the same. Different distances and same time result in different velocities. So the light balls move in all different directions with different velocities.
But a single firecracker is boring.
For celebrations, we would love to burst many crackers in a series. Also, at least 4 or 5 should burst simultaneously to cover up the empty space.
Step 3. Bursting many at a time ????
We use a variable called density that denotes the number of crackers that will burst simultaneously. The x and y coordinates (top and left positions) of each cracker are set randomly. We have two arrays x and y declared as state variables. Their values change at the end of every explosion, so every new explosion takes place at a new location on the screen.
import React from 'react';
import { Dimensions, StyleSheet, View, Animated, Easing } from 'react-native';
export default class Fireworks extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
x: [],
y: [],
};
this.fadingOpacity = new Animated.Value(1);
this.movingBall = new Animated.Value(0);
}
componentWillMount() {
this.setExplosionSpots()
}
setExplosionSpots() {
let density = 5,
x = [],
y = [];
for (i = 0; i < density; i++) {
x[i] = this.getRandom(Dimensions.get('window').width);
y[i] = this.getRandom(Dimensions.get('window').height);
}
this.setState({ x, y }, () => {
this.animateOpacity();
this.animateBall();
});
}
getRandom = (n) => {
return Math.round(Math.random() * n);
};
animateOpacity() {
this.fadingOpacity.setValue(1);
Animated.timing(this.fadingOpacity, {
toValue: 0,
duration: 700,
easing: Easing.ease,
useNativeDriver: false,
}).start(() => this.setExplosionSpots());
}
animateBall() {
this.movingBall.setValue(0);
Animated.timing(this.movingBall, {
toValue: 1,
duration: 700,
easing: Easing.ease,
useNativeDriver: false,
}).start();
}
explosionBox() {
let balls = [],
randomTops = [],
randomLefts = [],
randomColors = [];
for (let i = 0; i < 30; i++) {
balls.push('');
randomTops[i] = this.movingBall.interpolate({
inputRange: [0, 1],
outputRange: [100, this.getRandom(200)],
});
randomLefts[i] = this.movingBall.interpolate({
inputRange: [0, 1],
outputRange: [100, this.getRandom(200)],
});
randomColors[i] =
'rgb(' +
this.getRandom(255) +
',' +
this.getRandom(255) +
',' +
this.getRandom(255) +
')';
}
let ballOpacity = this.fadingOpacity.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
});
return (
<View style={styles.explosionBoundary}>
{balls.map((ball, index) => {
return (
<Animated.View
style={[
styles.ball,
{
top: randomTops[index],
left: randomLefts[index],
opacity: ballOpacity,
backgroundColor: randomColors[index],
},
]}
/>
);
})}
</View>);
}
render() {
const { x, y } = this.state;
return (
<View>
{x.map((item, index) => {
return (
<View
style={{
top: y[index],
left: x[index],
}}>
{this.explosionBox()}
</View>
)
})}
</View>)
}
}
const styles = StyleSheet.create({
explosionBoundary: {
position: 'absolute',
height: 200,
width: 200,
},
ball: {
position: 'absolute',
height: 7,
width: 7,
borderRadius: 3,
},
});Voilà! An amazing fireworks animation is ready:

Bonus- Circular firecrackers
Crackers are more elegant when they burst into a circular path. The above code can be modified a bit to produce circular crackers.
We used random values between 0 and 200 for the final x and y positions of the light balls, putting the initial position at the centre (100,100) of the explosion box. This made the balls to move in random directions.
To make their path circular we need to calculate the x and y positions of the balls with the help of a simple equation x² +y² = r². This is the equation for a circle in the simplest form when the centre of the circle lies at the origin. In our case, we have a square box (200 x 200) where we will make the circular path of explosion.

We use the above illustration to draw the circular path. The radius of the circle is 100 and the centre lies at (100,100).
So our equation will now become:
(x-100)² + (y-100)² = 100².
Using this equation we plot some 20 points in a circular path. At these points, we will draw our light balls. Also, we make the balls bigger as they explode.
This results in:

The complete code with several customization props is available on Github at this link: https://github.com/Abhinandan-Kushwaha/Fireworks.
Thanks a lot for stopping by and being patient. ❤
Book a Discovery Call
Related Articles.
More from the engineering frontline.
Dive deep into our research and insights on design, development, and the impact of various trends to businesses.

Apr 6, 2026
How We Built an AI System That Automates Senior Solution Architect Workflows
Discover how we built a 4-agent AI co-pilot that converts complex RFPs into draft technical proposals in 15 minutes — with built-in conflict detection, assumption surfacing, and confidence scoring.

Apr 6, 2026
AI Code Healer for Fixing Broken CI/CD Builds Fast
A deep dive into how GeekyAnts built an AI-powered Code Healer that analyzes CI/CD failures, summarizes logs, and generates code-level fixes to keep development moving.

Apr 2, 2026
A Real-Time AI Fraud Decision Engine Under 50ms
A deep dive into how GeekyAnts built a real-time AI fraud detection system that evaluates transactions in milliseconds using a hybrid multi-agent approach.

Apr 1, 2026
Building an Autonomous Multi-Agent Fraud Detection System in Under 200ms
GeekyAnts built a 5-agent fraud detection pipeline that makes decisions in under 200ms — 15x cheaper than single-model systems, with full explainability built in.

Mar 31, 2026
Building a Self-Healing CI/CD System with an AI Agent
When code breaks a pipeline, developers have to stop working and figure out why. This blog shows how an AI agent reads the error, finds the fix, and submits it for review all on its own.

Mar 26, 2026
Maestro Automation Framework — Advanced to Expert
Master Maestro at scale. Learn architecture, reusable flows, CI/CD optimization, and how to eliminate flakiness in production-grade mobile automation.Master Maestro at scale. Learn architecture, reusable flows, CI/CD optimization, and how to eliminate flakiness in production-grade mobile automation.