Skip to content
Render images as interactive particles
TypeScript JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.storybook throttled transformations Jan 28, 2020
public added some props Jan 25, 2020
src state change callbacks Feb 9, 2020
typings better performance by batching particles on canvas Jan 24, 2020
.babelrc init Jan 18, 2020
.editorconfig init Jan 18, 2020
.eslintrc.js init Jan 18, 2020
.gitignore interactive forces Feb 9, 2020
.nvmrc init Jan 18, 2020
.travis.yml init Jan 18, 2020
README.md Update README.md Feb 13, 2020
package-lock.json docs Feb 9, 2020
package.json docs Feb 9, 2020
rollup.config.js init Jan 18, 2020
tsconfig.declaration.json init Jan 18, 2020
tsconfig.json docs Feb 9, 2020
tsconfig.test.json init Jan 18, 2020
yarn.lock interactive forces Feb 9, 2020

README.md

react-particle-image

Render images as interactive particles

NPM JavaScript Style Guide

react-particles-demo-3

Install

npm install --save react-particle-image

Links

Simple Usage

codesandbox

import * as React from "react";
import ParticleImage, { ParticleOptions } from "react-particle-image";

const particleOptions: ParticleOptions = {
  filter: ({ x, y, image }) => {
    // Get pixel
    const pixel = image.get(x, y);
    // Make a particle for this pixel if blue > 50 (range 0-255)
    return pixel.b > 50;
  },
  color: ({ x, y, image }) => "#61dafb"
};

export default function App() {
  return (
    <ParticleImage
      src={"/react-logo.png"}
      scale={0.75}
      entropy={20}
      maxParticles={4200}
      particleOptions={particleOptions}
    />
  );
}

Complex Usage

codesandbox

import * as React from "react";
import useWindowSize from "@rooks/use-window-size";
import ParticleImage, {
  ParticleOptions,
  Vector,
  forces,
  ParticleForce
} from "react-particle-image";
import "./styles.css";

const particleOptions: ParticleOptions = {
  filter: ({ x, y, image }) => {
    // Get pixel
    const pixel = image.get(x, y);
    // Make a particle for this pixel if blue > 50 (range 0-255)
    return pixel.b > 50;
  },
  color: ({ x, y, image }) => "#61dafb",
  radius: () => Math.random() * 1.5 + 0.5,
  mass: () => 40,
  friction: () => 0.15,
  initialPosition: ({ canvasDimensions }) => {
    return new Vector(canvasDimensions.width / 2, canvasDimensions.height / 2);
  }
};

const motionForce = (x: number, y: number): ParticleForce => {
  return forces.disturbance(x, y, 5);
};

export default function App() {
  const { innerWidth, innerHeight } = useWindowSize();

  return (
    <ParticleImage
      src={"/react-logo.png"}
      width={Number(innerWidth)}
      height={Number(innerHeight)}
      scale={0.75}
      entropy={20}
      maxParticles={4000}
      particleOptions={particleOptions}
      mouseMoveForce={motionForce}
      touchMoveForce={motionForce}
      backgroundColor="#191D1F"
    />
  );
}

Performance Tips

ParticleImage has a target frame rate of 30fps, but with thousands of particles updating positions and repainting 30 times per second, performance can be a problem.

If animations are choppy try:

  • Reducing the number of distinct particle colors (particles of the same color will be batched while painting)
  • Reducing the number of particles (less than 6000 is ideal)
  • Reducing the resolution of the src image.

Here's a codesandbox of a good boy to show what I mean. Note the round function to reduce the number of colors painted on the canvas.

MIT © malerba118

You can’t perform that action at this time.