Library / SDK
drawcall/Proton avatar
drawcall/Proton

Proton (proton-engine): a JavaScript particle engine for canvas and WebGL

Javascript particle animation library

2,477 stars281 forksJavaScriptMIT

At a glance

What is it?
Proton, published on npm as proton-engine, is an MIT-licensed particle animation library for canvas, DOM, WebGL and other renderers. It is a good fit when you want emitters, behaviours and physics without adopting a full game engine, and a poor fit when you need a maintained release cadence or 3D particles.
Who is it for?
Adopt Proton if you are building 2D particle effects for a canvas, DOM or WebGL scene and want emitter, initializer and behaviour objects you can compose in a dozen lines. Do not adopt it if you need 3D particles (the README points to three.proton separately) or if you depend on a steady stream of releases, because the latest release listed is v5.4.3 from 2022-04-28 while package.json declares 7.1.5.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 7 months ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What proton-engine solves, and who ends up using it

Particle effects are a small problem with a large amount of bookkeeping. You need a spawn rate, a lifetime, a starting size, a velocity direction, a colour ramp, an alpha fade, and a loop that moves every particle each frame and removes the dead ones. Writing that by hand is not hard, but it is repetitive, and every effect you add duplicates the same loop with different numbers. Proton packages the bookkeeping into objects: an Emitter holds the configuration, Initialize objects set per-particle properties at birth, Behaviour objects mutate those properties over time, and a Renderer draws the result. The README describes the library as lightweight and lists flames, fireworks, bullets and explosions as typical outputs.

The audience is web developers working in 2D. The README says Proton can be used inside react, vue, angular, pixi.js and Phaser, which tells you the intended position: a rendering-agnostic effect layer that sits beside whatever already owns your canvas or scene graph, rather than a framework that owns the page. If you are building a marketing page with a confetti burst, a game with muzzle flashes, or a data visualisation with drifting points, that is the target case. If you need a full physics engine with collision response between rigid bodies, Proton is not that, and the README does not claim it is.

How the emitter, initializer and behaviour pipeline actually runs

The mechanism is a per-particle property bag plus a fixed update loop. An Emitter carries a rate, which the README example writes as new Rate(new Span(10, 20), 0.1), meaning a span of ten to twenty particles with a delay argument. Each particle that the emitter produces is passed through the initializers attached with addInitialize: Radius sets size, Life sets how long the particle survives, Velocity sets a speed and angle. The README's Velocity example uses the string "polar" as the third argument, which tells the engine to interpret the span as an angle in degrees rather than a vector component. After initialization, behaviours added with addBehaviour run on every tick. Color("ff0000", "random") picks a random colour from the red value, and Alpha(1, 0) fades the particle from opaque to transparent.

The emitter has a position object exposed as emitter.p, and the README sets emitter.p.x and emitter.p.y to the centre of the canvas before calling emitter.emit(5). That call is a one-shot emission of five particles, which is how you produce a burst rather than a stream. The emitter is then registered with proton.addEmitter(emitter), and a renderer is registered with proton.addRenderer(renderer). The engine drives the loop, the renderer draws. Because the renderer is a separate object, swapping CanvasRenderer for WebGLRenderer or DomRenderer is a change at the registration site, not a rewrite of the effect.

Two details in the README matter more than they look. First, Span is described as being everywhere, and the README states that understanding it lets you create almost any effect. Span is the range abstraction that lets a single configuration produce varied particles instead of a uniform field. Second, the README notes that Body and Color used together are better served by WebGLRenderer than CanvasRenderer, which is a candid admission that the canvas path has limits once you start compositing bodies and colours per particle.

Installing proton-engine and emitting your first particles

The npm package name changed, and this trips people up. The README states plainly that the package name moved from proton-js to proton-engine, so any tutorial or snippet importing from proton-js is stale. Install with npm, then import the default export plus the named classes you need.

bash
npm install proton-engine --save
javascript
import Proton from "proton-engine";

The README also supports a plain script tag for pages without a bundler, loading a prebuilt file:

html
<script type="text/javascript" src="js/proton.web.min.js"></script>

With the import in place, the smallest useful effect is an emitter with a rate, a few initializers, a couple of behaviours, and a canvas renderer. The README's own example is the reference here, and it is worth typing rather than copying so you see which arguments are spans and which are scalars.

javascript
import Proton, {
  Emitter, Rate, Span, Radius, Life, Velocity, Color, Alpha, CanvasRenderer,
} from "proton-engine";

const proton = new Proton();
const emitter = new Emitter();
emitter.rate = new Rate(new Span(10, 20), 0.1);
emitter.addInitialize(new Radius(1, 12));
emitter.addInitialize(new Life(2, 4));
emitter.addInitialize(new Velocity(3, new Span(0, 360), "polar"));
emitter.addBehaviour(new Color("ff0000", "random"));
emitter.addBehaviour(new Alpha(1, 0));

Set the emitter position to the centre of the canvas, register the emitter and a renderer, and the engine starts drawing on its own loop:

javascript
emitter.p.x = canvas.width / 2;
emitter.p.y = canvas.height / 2;
emitter.emit(5);
proton.addEmitter(emitter);
const renderer = new CanvasRenderer(canvas);
proton.addRenderer(renderer);

What you should see is a short burst of five red particles at the centre of the canvas, each between one and twelve pixels in radius, living two to four seconds, flying outward at speed three in a random polar direction, and fading out. If you want a continuous stream rather than a burst, drop the emit(5) call and rely on the rate. Two tuning notes from the README: set proton.fps = 60 if you want to hold a stable sixty frames on a high-refresh display, and set Proton.USE_CLOCK = true if you prefer clock-based Euler integration over the default.

Where Proton stops being the right tool

The most concrete limitation is dimensional. Proton is a 2D engine, and the README does not pretend otherwise: it links to three.proton as the 3D version, hosted in a separate repository. If your scene is a 3D space and you want particles to move in depth, you are looking at a different project with a different API, not a flag on this one.

The second limitation is the renderer split. The README advises WebGLRenderer over CanvasRenderer when you combine Body and Color. That is a direct statement that the canvas path does not handle that combination as well, so a project that has settled on a 2D canvas context for other reasons may hit a ceiling precisely where the effects get interesting. The DomRenderer is described as supporting hardware acceleration, which implies the plain DOM path is the fallback rather than the fast path.

The third is release cadence, and it is the one to weigh hardest. The most recent release listed is v5.4.3 from 2022-04-28, while package.json in the repository declares version 7.1.5. The last push to the repository was on 2026-03-06, so work has happened since that release, but the published release record and the package manifest do not line up. The README itself still says Proton has been upgraded to the v4 version, which is older than both. For a project you plan to depend on for years, that divergence between what is tagged, what is in package.json, and what the README claims is the thing to resolve before you build on it. None of this means the code is abandoned, but it does mean you cannot infer the shipping version from the documentation alone.

How Proton differs from a general animation library or a full game engine

The natural alternative for a browser effect is a general-purpose animation library such as GSAP, and the difference is in what the abstraction is centred on. A tweening library animates properties of objects you have already created: you declare that this element's opacity goes from one to zero over two seconds, and the library interpolates. Proton inverts that. You do not create particles and animate them; you declare an emitter configuration, and the engine creates, updates and destroys particles for you. Population management is the product. That is why Life, Rate and Span exist as first-class concepts, and why there is no equivalent of a timeline in the README's usage example.

The trade-off runs the other way too. Because Proton owns the particle lifecycle, you give up fine control over individual particles unless you reach into the emitter's particle list, and the README does not document that path. If your effect is five elements moving on a curve, a tweening library is simpler and you should use one. Proton earns its place when the count is in the hundreds or thousands and hand-managing each one stops being reasonable.

Within the particle space, the README points at two related projects rather than competitors: three.proton for 3D, and a React wrapper at lindelof/particles-bg. If you are in React and want a background effect rather than a custom simulation, the wrapper is the shorter path, and choosing it means giving up direct control of the emitter graph that the core library exposes.

Licence, maintenance and what an upgrade costs you

Proton is released under the MIT License, stated both in the README and in the license field of package.json. MIT is permissive: it allows commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a statement about the licence text, not legal advice, and if your organisation has a policy on attribution in bundled output, check it against the actual LICENSE file in the repository, which is present at the top level.

Upgrade cost is the harder question. The README notes that the library was upgraded to v4 with performance improvements and API changes, and points to the release notes for details. That tells you the project has shipped breaking API changes before, so a major version bump is not a drop-in. The practical risk today is narrower: the release list ends at v5.4.3 while package.json says 7.1.5, and the README's usage example is labelled as a v4-era introduction. Before upgrading or adopting, read the release notes for the versions between your current one and the target, and confirm which build the npm package you install actually contains. The build pipeline is standard for a library of this size: npm install, npm run build with rollup, and npm start to serve the examples on port 3001, which the README documents as the way to run the example directory.

Editorial conclusion

Adopt Proton if you are building 2D particle effects for a canvas, DOM or WebGL scene and want emitter, initializer and behaviour objects you can compose in a dozen lines. Do not adopt it if you need 3D particles (the README points to three.proton separately) or if you depend on a steady stream of releases, because the latest release listed is v5.4.3 from 2022-04-28 while package.json declares 7.1.5. Verify first which version npm actually resolves for proton-engine and whether the API you plan to use matches that build, then check the TypeScript guidance in issue 109 before you commit to typed imports.

Frequently asked questions

How do I install proton-engine in a JavaScript project?

Run npm install proton-engine --save, then import the default export from "proton-engine". The README notes the npm package name changed from proton-js to proton-engine, so older snippets may use the wrong name.

Can I use Proton without a bundler, directly in HTML?

Yes. The README gives a script tag example loading js/proton.web.min.js, which is the path for pages that do not run a module bundler.

Does proton-engine support 3D particles?

Not in this repository. The README links to a separate project, three.proton, as the 3D version of the engine, so 3D work means a different codebase and API.

Why does Proton need proton.fps set to 60?

The README states that in modern browsers, if the FPS exceeds 60 and you want to hold a stable 60 FPS, you need to set proton.fps = 60. This matters when the host game engine has a fixed frame rate or the display has a high refresh rate.

Which renderer should I use with Proton?

The README lists CanvasRenderer, DomRenderer, WebGLRenderer, PixelRenderer, EaselRenderer and a custom renderer option. It advises using WebGLRenderer rather than CanvasRenderer when you use Proton.Body and Proton.Color at the same time.

Official sources

  1. drawcall/Proton on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/drawcall-proton.svg)](https://hysenlabs.com/projects/drawcall-proton)