DEV Community

Cover image for [JS] How to create beautiful and realistic confetti animation with tsParticles
Matteo Bruni for tsParticles

Posted on • Edited on

[JS] How to create beautiful and realistic confetti animation with tsParticles

Starting from version 1.30.0 tsParticles has new options to create beautiful and realistic confetti animations with every supported particle shape.

Every parameter of the animation can be configured so you can choose which configuration will suit you better.

Let's build this sample configuration:

Background



background: {
  color: {
    value: "#000000"
  }
}


Enter fullscreen mode Exit fullscreen mode

This sets the black background to the canvas, this is optional, you can have a transparent background omitting this section.

Full Screen



fullScreen: {
  enable: true,
  zIndex: -1
}


Enter fullscreen mode Exit fullscreen mode

This sets the canvas to full screen with a zIndex of -1, be careful with zIndex set to -1, this will be below every page element, you can set it to an higher value but the interactivity.detectsOn should be "window" to have particles on top without losing the website interactivity.

Interactivity



interactivity: {
  detectsOn: "window"
}


Enter fullscreen mode Exit fullscreen mode

This was explained above, the detectsOn property set to "window" disabled canvas pointer events, so you can interact with any elements below the canvas zIndex. This should be set like with an high zIndex, with a -1 value it's not necessary.

Emitter



emitters: {
  position: {
    x: 50,
    y: 100
  },
  rate: {
    quantity: 10,
    delay: 0.25
  }
}


Enter fullscreen mode Exit fullscreen mode

Everyone loves particles cannons, here you are, you have a bottom centered cannon that shoots 10 particles every 0.25 seconds.

The position is specified in percent values, not in pixels, so 100 set to y is the bottom of the page, while 50 to x is the horizontal center.

Particles configuration

This is the biggest part, where you can configure every aspect of your particles, or confetti if preferred.



particles: {
  /* ... */
}


Enter fullscreen mode Exit fullscreen mode

Color



color: {
  value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"]
}


Enter fullscreen mode Exit fullscreen mode

You can set here a single value, or an array of string (or more complex object, but let's keep things simple for now).

This value is not applied to emojis and images (they are already colored).

Number



number: {
  value: 0
}


Enter fullscreen mode Exit fullscreen mode

The particles number is set to 0 because the particles are shot from the emitter and only those should be used.

If this values is set to any positive value will load random particles in the canvas.

Move



move: {
  decay: 0.05,
  direction: "top",
  enable: true,
  speed: {
    min: 50,
    max: 75
  },
  /* ... */
}


Enter fullscreen mode Exit fullscreen mode

This section will configure particles movements inside the canvas, you can apply gravity, speed, directions and other properties.

Some values can be seen above:

  • decay: it's a value used to slow down particles
  • direction: it's the particles direction, you can set a value like "top", "top-right", "right" or an angle in degrees.
  • enable: this value must be true if you want particles to move, otherwise they will be static
  • speed: this value can be a single numeric value or an object like the one above with min/max properties and each particle will pick one value in that range randomically

Gravity



gravity: {
  enable: true
}


Enter fullscreen mode Exit fullscreen mode

This section part of the move options will configure particles gravity, you can just enable it with a default earth gravity (9.81) and a max speed of 50

Out Modes



outModes: {
  top: "none",
  default: "destroy"
}


Enter fullscreen mode Exit fullscreen mode

This section sets the action to do when particles will go off canvas, you can specify this for every border (top, left, bottom, right) or a default that will be overridden by specific values like in this case, the particle will not be destroyed only if it goes outside the top edge.

Opacity



opacity: {
  value: 1
}


Enter fullscreen mode Exit fullscreen mode

This value sets the particles (ops, confetti) opacity value. This can be also a range value like the previous seen move.speed.

Size



size: {
  value: 8
}


Enter fullscreen mode Exit fullscreen mode

This value sets the particles (ops, confetti) radius value. This can be also a range value like the previous seen move.speed.

Rotate



rotate: {
  value: {
    min: 0,
    max: 360
  },
  direction: "random",
  animation: {
    enable: true,
    speed: 60
  }
}


Enter fullscreen mode Exit fullscreen mode

This section sets the particles rotation around its center. You can specify a degree angle to value or a range of angles like the move.speed above. In this case any angle will be picked randomly by each particle.

The direction property sets the rotation direction, this property can have 3 values:

  • "clockwise"
  • "counter-clockwise"
  • "random"

The first two are clear, the third value ("random") make every particle choose one of the two previous values randomically, so you can see particles rotates clockwise and counter clockwise.

The animation property make the particle rotation animated, otherwise the particle will only have the initial angle. The rotation speed can be set and the animation can be enabled, by default is not.

Tilt



tilt: {
  direction: "random",
  enable: true,
  value: {
    min: 0,
    max: 360
  },
  animation: {
    enable: true,
    speed: 30
  }
}


Enter fullscreen mode Exit fullscreen mode

This is the first of the new three particles options, tilt will deform the particles like they are seen from another perspective spinning around its center.

The properties of this property are the same seen in the rotate section above and it works exactly the same.

Roll



roll: {
  darken: {
    enable: true,
    value: 25
  },
  enable: true,
  speed: {
    min: 5,
    max: 15
  }
}


Enter fullscreen mode Exit fullscreen mode

This is the second new property of particles options, roll will deform the particles like they are seen rolling around its center making a natural falling effect.

The properties of this section are really simple, enable will activate this effect, speed sets the fall effect speed.

What about darken?

There are 3 more options after speed and enable:

  • backColor: This sets the back color of the particles when their back is visible
  • darken: This is the first alternative when backColor is not set, this will darken by the specified value the particles color create a nice simple shadow
  • enlighten: This is the latest alternative if none of the above are set or enabled, this will enlighten by the specified value the particles color create a nice simple light effect

In this case the particles (only the one that can be colored) will have a nice shadow while rolling down.

Wobble



wobble: {
  distance: 30,
  enable: true,
  speed: {
    min: -15,
    max: 15
  }
}


Enter fullscreen mode Exit fullscreen mode

This is the latest (but not least) new effect introduced in 1.30.

This effects makes the particles bouncing from left to right simulating air resistance with a really nice effect.

The properties are really simple, enable for activating this, the distance used for enlarging the angle and the wobbling speed.

About the speed I recommend a range with a min and a max opposite values instead of a single value since the effect is nicer. If only a positive or negative value is set the particles will only wobble right or left.

Shape



shape: {
  type: /* ... */
  /* ... */
}


Enter fullscreen mode Exit fullscreen mode

Why shape is the latest section explained? Because in this case it's really huge because I want to show all possibilities in the sample but you can choose from:

  • circle
  • square
  • polygon
  • line (be careful, this will only works with the stroke color since it's not fillable)
  • character (also emojis are accepted or any font like FontAwesome if correctly installed)
  • image
  • triangle
  • star
  • bubble (external plugin)
  • heart (external plugin)
  • multiline text (external plugin)
  • rounded rect (external plugin)
  • spiral (external plugin, this will be better with stroke color since filled it's kinda ugly)

For each shape you can specify additional options like this:



shape: {
  type: "circle",
  options: {
    circle: {
      particles: {
        size: {
          value: 10
        }
      }
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

The code below is the sample used in the codepen shown at the beginning.

The polygon options are an array and are randomly picked by each particles creating a pentagon or an hexagon.

The character options specifies the font used by the specified character, the weight, an additional style, and the text to be used for each particle, in this case one emoji per particle randomly picked.

The images are a lot and random picked, they have a bigger size value since they have some padding inside.



shape: {
    type: [
        "circle",
        "square",
        "polygon",
        "character",
        "character",
        "character",
        "image",
        "image",
        "image"
    ],
    options: {
        polygon: [
            {
                sides: 5
            },
            {
                sides: 6
            }
        ],
        character: [
            {
                font: "Verdana",
                value: ["💩", "🤡", "🍀", "🍙", "🦄", "⭐️"],
                style: "",
                weight: 400
            }
        ],
        image: [
            {
                src: "https://particles.js.org/images/fruits/apple.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/avocado.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/banana.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/berries.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/cherry.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/grapes.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/lemon.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/orange.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/peach.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/pear.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/pepper.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/plum.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/star.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/strawberry.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/watermelon.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            },
            {
                src: "https://particles.js.org/images/fruits/watermelon_slice.png",
                width: 32,
                height: 32,
                particles: {
                    size: {
                        value: 16
                    }
                }
            }
        ]
    }
}


Enter fullscreen mode Exit fullscreen mode

Hope you'll have a lot of fun with tsParticles and the new animations to make beautiful confetti

GitHub logo tsparticles / tsparticles

tsParticles - Easily create highly customizable JavaScript particles effects, confetti explosions and fireworks animations and use them as animated backgrounds for your website. Ready to use components available for React.js, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Inferno, Solid, Riot and Web Components.

Top comments (11)

Collapse
 
markwright profile image
markwrightdev

Awesome effects! Thanks for sharing

Collapse
 
jonerikj profile image
jonerikj

This is great! Is it possible to have the animation stop after running for 30 seconds?

Collapse
 
matteobruni profile image
Matteo Bruni

You can set a timer and stop the animation

Collapse
 
jonerikj profile image
jonerikj

Thank you! Unfortunately I am very far from being a developer :P Any chance you could show how to include the timer inside the code? :)

Thread Thread
 
matteobruni profile image
Matteo Bruni
const container = await tsParticles.load("tsparticles", { /* your options */ });

setTimeout(() => {
  container.stop();
}, 5 /* seconds */ * 1000);
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
jonerikj profile image
jonerikj

Thank you. Where exactly do I place this in the code? Sorry for my lack of knowledge to coding.

Thread Thread
 
matteobruni profile image
Matteo Bruni

This is a replacement of the sample seen in the article. You have to keep the previous options, since I've cut them in the sample for readability.

Thread Thread
 
jonerikj profile image
jonerikj

Hmm 🤔 Still not able to make it work. Sorry for being a noob. I have tried placing this code in top and bottom of the js:
codepen.io/jon-erik-josephsen-the-...

Thread Thread
 
matteobruni profile image
Matteo Bruni

Ok you just missed the async function: codepen.io/matteobruni/pen/qBxvjLK

Or you can achieve something a little bit different using emitters life options: codepen.io/matteobruni/pen/eYVXRxR

Thread Thread
 
jonerikj profile image
jonerikj

Perfect! Thank you very much! 😁

Collapse
 
amircahyadi profile image
Amir-cahyadi

👍 ty