Arek Nawo Hobbyist. Programmer. Dreamer. Freelancer. JavaScript and TypeScript lover. 👍 World-a-better-place maker. 🌐

Creating interactive backgrounds in React with tsParticles

6 min read 1849

Creating interactive backgrounds in React with tsParticles

From 3D illustrations to animated backgrounds and scroll-based storytelling — interactive content is the go-to solution if you’re trying to stand out on the web. While it certainly requires more time and experience to implement well, the outcome can be truly stunning.

With that said, in this article, I’d like to show you a shortcut to implementing an interactive background on your website with just a tiny bit of effort. That shortcut is tsParticles — a library that helps you create interactive particle backgrounds. With its help, you’ll be able to create stunning visuals in no time!

The tsParticles landing page

What is tsParticles

tsParticles is a spiritual successor of particles.js, an older library of similar functionality. The improvements include the use of TypeScript, first-party integrations with leading frameworks, and some new features. Other than that, the library is backward-compatible with particles.js — all configuration options are the same.

The library uses HTML Canvas to create backgrounds that are far more advanced than just dots floating on the screen — some examples include particle masks for underlying images, making for a nice reveal effect, or polygon masks for organizing particles within a vector shape. You can also use custom graphics for the particles, apply custom animations, manage effects triggered by different user actions, and so much more!

Overall, the library is incredibly versatile and configurable despite using just a single config object. Additionally, TypeScript typings and dedicated integrations for not only React, Vue, and Angular but also frameworks like Svelte and Solid make for a great development experience.

Creating interactive backgrounds

To show how to use tsParticles, we will explore a few unique, interactive backgrounds. This should give you a good view of what’s possible and get you to know some of the config options.

Setup

We’ll be using React and the official tsParticles React component for this demo. The following commands set up a React Vite template, install the necessary dependencies, and run the development server so that you’re ready to go in just a few seconds.

npm init [email protected] backgrounds --template react-ts
cd backgrounds
npm install react-tsparticles
npm run dev

To start using tsParticles, import and render the Particles component inside src/app.tsx file.

import Particles, { ISourceOptions } from "react-tsparticles";

const App = () => {
  const options: ISourceOptions = {
    // ...
  };

  return <Particles options={options} />;
};

export default App;

The component accepts several props — the most important of which is options because it’s responsible for configuring pretty much all aspects of tsParticles’ visuals. The other props configure the canvas or wrapper elements, provide access to the tsParticles instance for additional control, and more.

We made a custom demo for .
No really. Click here to check it out.

Configuration options

Focusing on the options, let’s use them to create our first interactive background.

// ...
const options: ISourceOptions = {
  background: {
    color: "#0d47a1",
  },
  interactivity: {
    events: {
      onClick: {
        enable: true,
        mode: "push",
      },
      onHover: {
        enable: true,
        mode: "repulse",
      },
      resize: true,
    },
    modes: {
      bubble: {
        distance: 400,
        duration: 2,
        opacity: 0.8,
        size: 40,
      },
      push: {
        quantity: 4,
      },
      repulse: {
        distance: 200,
        duration: 0.4,
      },
    },
  },
  particles: {
    color: {
      value: "#ffffff",
    },
    links: {
      color: "#ffffff",
      distance: 150,
      enable: true,
      opacity: 0.5,
      width: 1,
    },
    collisions: {
      enable: true,
    },
    move: {
      direction: "none",
      enable: true,
      outMode: "bounce",
      random: false,
      speed: 6,
      straight: false,
    },
    number: {
      density: {
        enable: true,
        value_area: 800,
      },
      value: 80,
    },
    opacity: {
      value: 0.5,
    },
    shape: {
      type: "circle",
    },
    size: {
      random: true,
      value: 5,
    },
  },
};
// ...

The above configuration creates one of the most recognizable particle-based backgrounds in the form of interconnected dots:

See the Pen
tsParticles Floating Particles
by Arek Nawo (@areknawo)
on CodePen.

Configuring tsParticles is relatively straightforward, and thanks to TypeScript typings, you don’t have to memorize or read the documentation to get to know all the options.
Here are some details about the options to get you started:

  • background configures everything that’s behind particles. You can use solid colors in various formats (HEX, RGB, HSL, etc.), images, different opacities, and more
  • interactivity controls what happens when the user clicks or hovers over the background
  • events defines how to handle selected events
  • modes configure actions used for event handling
  • particles groups all properties that control how the particles and related visuals are displayed. From here, you can configure everything from the color and movement behavior of the particles, to the connection lines between them

tsParticles provides a ton more options, all of which you can explore through TypeScript-powered autocompletion or the official documentation.

Creating a confetti effect

Now that we have a basic understanding of how tsParticles works, let’s create something more interesting. We’ll implement a confetti effect, similar to what you can send in Apple iMessages.

Instead of just particles floating around, we’ll use a particle emitter to achieve the impression of confetti exploding from a single point. Let’s create one using the following config.

// ...
const options: ISourceOptions = {
  fullScreen: true,
  fpsLimit: 60,
  detectRetina: true,
  emitters: {
    startCount: 0,
    position: { x: 50, y: 50 },
    size: {
      width: 0,
      height: 0,
    },
    rate: {
      delay: 0,
      quantity: 10,
    },
    life: {
      duration: 0,
      count: 1,
    },
  },
};
// ...

Using the above parameters in the emitters section, we create an invisible emitter right in the center of the fullscreen canvas. The life object specifies that there’ll be only one emitter for an infinite duration of time. Also, according to the values of the rate object, the emitter will emit ten particles with no delay.

With such a setup, all that’s left to do is specify how the emitted particles should look and behave. For that, set the following options in the particles section.

// ...
const options: ISourceOptions = {
  // ...
  emitters: {
    // ...
  },
  particles: {
    number: {
      value: 0,
    },
    color: {
      value: ["#FF5A86", "#953AFE", "#FFC326", "#46C0FF"],
    },
    shape: {
      type: ["square", "circle"],
    },
    opacity: {
      value: 1,
      animation: {
        enable: true,
        minimumValue: 0,
        speed: 0.5,
        startValue: "max",
        destroy: "min",
      },
    },
    size: {
      value: 5,
    },
    links: {
      enable: false,
    },
    life: {
      duration: {
        sync: true,
        value: 3,
      },
      count: 1,
    },
    move: {
      angle: {
        value: 45,
        offset: 0,
      },
      drift: {
        min: -0,
        max: 0,
      },
      enable: true,
      gravity: {
        enable: true,
        acceleration: 20,
      },
      speed: 90,
      decay: 1 - 0.9,
      direction: -90,
      random: true,
      straight: false,
      outModes: {
        default: "none",
        bottom: "destroy",
      },
    },
    rotate: {
      value: {
        min: 0,
        max: 360,
      },
      direction: "random",
      animation: {
        enable: true,
        speed: 60,
      },
    },
    tilt: {
      direction: "random",
      enable: true,
      value: {
        min: 0,
        max: 360,
      },
      animation: {
        enable: true,
        speed: 60,
      },
    },
    roll: {
      darken: {
        enable: true,
        value: 25,
      },
      enable: true,
      speed: {
        min: 15,
        max: 25,
      },
    },
    wobble: {
      distance: 20,
      enable: true,
      speed: {
        min: -15,
        max: 15,
      },
    },
  },
};
// ...

In general, the above configuration makes particles imitate confetti. They have different colors, shapes, and can move, rotate, tilt, and more. The most important options here are:

  • number.value, which controls the number of floating particles (should be 0)
  • move.gravity, which enables a force that’ll pull particles down

Here’s the final result:

See the Pen
tsParticles Colorful Confetti
by Arek Nawo (@areknawo)
on CodePen.

Presets

As you can see, tsParticles configurations can get pretty complex. To solve that, there’s a preset functionality so that you can share and reuse them.

You can also use any of the official or community presets and apply your custom options on top of them to achieve the effect you want even faster.

To show you how to use presets, we’ll use the sea-anemone preset, which spawns tentacle-like particles from the center of the canvas.

First, install the preset package from npm:

npm install tsparticles-preset-sea-anemone

To load the preset, you’ll need access to the tsParticles instance. For that, use the init prop to set the callback function to be used when you initialize tsParticles. The callback will receive said instance as a parameter.

import Particles, { ISourceOptions, Main } from "react-tsparticles";
import { loadSeaAnemonePreset } from "tsparticles-preset-sea-anemone";

const App = () => {
  const options: ISourceOptions = {
    preset: "seaAnemone",
  };
  const initialize = (instance: Main) => {
    loadSeaAnemonePreset(instance);
  };

  return <Particles options={options} init={initialize} />;
};

export default App;

In options, make sure to specify the preset by its name and include any other properties you want to customize. By default, the preset should give the following effect:

See the Pen
tsParticles Sea Anemone Preset
by Arek Nawo (@areknawo)
on CodePen.

As we mentioned before, tsParticles allows you to define your own presets as well. To do so, simply define your preset options and create a loading function that accepts your tsParticles instance as an argument. Inside the function, register the preset using instance’s addPreset method, passing your custom name and defined options.

// ...
const options: ISourceOptions = {
  // preset options
};
const loadCustomPreset = (main: Main) => {
  main.addPreset("customPreset", options);
};

Using such a preset is exactly the same as using a third-party one.

// ...

const App = () => {
  const options: ISourceOptions = {
    preset: "customPreset",
  };
  const initialize = (instance: Main) => {
    loadCustomPreset(instance);
  };

  return <Particles options={options} init={initialize} />;
};

Other customizations

On top of all the above, tsParticles allows even more advanced customization through plugins and advanced config options.

A plugin is very similar to a preset — it’s a function that accepts the tsParticles instance and alters it using one of the available methods. Apart from defining presets with addPreset, you can add custom particle shapes with addShape or allow for custom interactions using addInteractor.

To give you an example of how easy it is to create your own plugins, let’s create one that adds a hexagonal shape to tsParticles.

const loadHexagonShape = (main: Main) => {
  main.addShape("hexagon", (context, particle, radius) => {
    const angle = (2 * Math.PI) / 6;

    context.beginPath();
    for (let i = 0; i < 6; i++) {
      context.lineTo(
        radius * Math.cos(angle * i),
        radius * Math.sin(angle * i)
      );
    }
    context.closePath();
    context.stroke();
  });
};

The shape is drawn using HTML Canvas context and supplied particle configuration, similar to how it looked in our confetti demo.

See the Pen
tsParticles Colorful Hexagon Confetti
by Arek Nawo (@areknawo)
on CodePen.

Apart from plugins, there are also many advanced config options that can help you achieve the desired effect. The emitters property used in the confetti demo is one of them, and there are many more! Notable examples include the polygon property for specifying what vector shape the particles should cover, and the absorbers property for creating the opposite of an emitter — a black-hole-like entity that absorbs nearby particles.

Add the following bit in your config to create an absorber in a specific position that’ll grow in size (up to a certain limit) as it absorbs more particles.

// ...
const options: ISourceOptions = {
  // ...
  absorbers: {
    color: "#ffffff",
    position: { x: 70, y: 50 },
    size: {
      value: 50,
      limit: 150
    }
  }
  // ...
};
// ...

Here’s what happens when we apply it to our confetti demo.

See the Pen
tsParticles Colorful Hexagon Confetti
by Arek Nawo (@areknawo)
on CodePen.

Overall, there’s certainly a lot of customization possibilities with this library. Because of that, one can easily get lost when trying to achieve a particular effect. In this case, I recommend checking out the library author’s CodePen collection, which contains all kinds of configurations to use and take inspiration from. Here are a few of my favorites:

See the Pen
tsParticles polygon mask with multiple paths
by Matteo Bruni (@matteobruni)
on CodePen.

See the Pen
tsParticles Polygon Mask
by Matteo Bruni (@matteobruni)
on CodePen.

See the Pen
tsParticles external Perlin Noise Generator
by Matteo Bruni (@matteobruni)
on CodePen.

Conclusion

So, as you can see, the possibilities of the tsParticles library are almost endless. It’s safe to say that you can customize pretty much all of the aspects of the library. However, the best thing about that is that it’s gradual — you can customize as little or as much as you want, while the library will always have your back.

With libraries like tsParticles, bringing interactive visuals to your own website has never been easier. It’s now your turn to put it to good use and create something special!

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Arek Nawo Hobbyist. Programmer. Dreamer. Freelancer. JavaScript and TypeScript lover. 👍 World-a-better-place maker. 🌐

Leave a Reply