Jun 23, 2020

Bursting Colourful Crackers With react-native-fireworks

An npm package to burst crackers in your React native app.

Author

Abhinandan Kushwaha
Abhinandan KushwahaSoftware Engineer
Bursting Colourful Crackers With react-native-fireworks
 “Don’t let anyone ever dull your sparkle .” ― Unknown ✨✨

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:

react-native-firework-animation-display

 


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:

Circular firecrackers in react native


 

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

Recaptcha Failed.

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.

From Manual Testing to AI-Assisted Automation with Playwright Agents
Article

Apr 23, 2026

From Manual Testing to AI-Assisted Automation with Playwright Agents

This blog discusses the value of Playwright Agents in automating workflows. It provides a detailed description of setting up the system, as well as a breakdown of the Playwright Agent’s automation process.

The Keyboard Bounce of Death: Handling Inputs on Complex React Native Screens
Article

Apr 14, 2026

The Keyboard Bounce of Death: Handling Inputs on Complex React Native Screens

Fix the React Native ‘Keyboard Bounce of Death.’ Learn why inputs jump and how to build smooth, production-ready forms with modern architecture.

From RFPs to Revenue: How We Built an AI Agent Team That Writes Technical Proposals in 60 Seconds
Article

Apr 9, 2026

From RFPs to Revenue: How We Built an AI Agent Team That Writes Technical Proposals in 60 Seconds

GeekyAnts built DealRoom.ai — four AI agents that turn RFPs into accurate technical proposals in 60 seconds, with real-time cost breakdowns and scope maps.

How We Built an AI System That Automates Senior Solution Architect Workflows
Article

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.

AI Code Healer for Fixing Broken CI/CD Builds Fast
Article

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.

A Real-Time AI Fraud Decision Engine Under 50ms
Article

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.

Scroll for more
View all articles