Skip to main content

Overview

The SDK provides two approaches to particles:
  • <ParticleEmitter> — high-level emitter backed by @barvynkoa/particle-emitter. Driven by a JSON config and a spritesheet asset key.
  • <ParticleContainer> + <Particles> — lower-level approach using PixiJS’s native PIXI.ParticleContainer. You control initialisation and per-frame update logic directly.

<ParticleEmitter>

A declarative particle emitter. Reads its texture from stateApp.loadedAssets using key, upgrades the config to the latest format, and drives the emitter on the PixiJS ticker. The emitter is destroyed automatically when the component is unmounted.

Props

key
string
required
Asset manifest key for the particle spritesheet (type: 'spriteSheet'). The loaded texture array is passed to the emitter config automatically.
config
EmitterConfigV3 | EmitterConfigV2 | EmitterConfigV1
required
The particle emitter configuration object. All three config versions from @barvynkoa/particle-emitter are accepted — the SDK upgrades older formats automatically via upgradeConfig.
emit
boolean
When true, reinitialises the emitter with the current config. Toggle this to trigger a burst or restart emission. Synced from Emitter.emit.
emitSpeed
number
A multiplier applied to ticker.deltaMS before calling emitter.update(). Controls the effective simulation speed. Default 0.00234.
spawnChance
number
Probability (0–1) that a particle will spawn on any given update. Inherited from Emitter. Default 1.
maxParticles
number
Maximum number of live particles at any time. Inherited from Emitter.
particleConstructor
typeof Particle
Custom particle class constructor. Inherited from Emitter.

Emitter config

The config prop accepts the EmitterConfigV3 format from @barvynkoa/particle-emitter. Key fields:
import type { EmitterConfigV3 } from '@barvynkoa/particle-emitter';

const config: EmitterConfigV3 = {
  lifetime: { min: 0.5, max: 1.5 },
  frequency: 0.008,
  spawnChance: 1,
  maxParticles: 100,
  pos: { x: 0, y: 0 },
  addAtBack: false,
  behaviors: [
    {
      type: 'alpha',
      config: { alpha: { list: [{ value: 1, time: 0 }, { value: 0, time: 1 }] } },
    },
    {
      type: 'scale',
      config: { scale: { list: [{ value: 1, time: 0 }, { value: 0.3, time: 1 }] } },
    },
    {
      type: 'moveSpeed',
      config: { speed: { list: [{ value: 200, time: 0 }, { value: 100, time: 1 }] } },
    },
    {
      type: 'spawnShape',
      config: { type: 'torus', data: { x: 0, y: 0, radius: 10 } },
    },
  ],
};

Example

<!-- Asset manifest: sparks: { type: 'spriteSheet', src: '/fx/sparks.json' } -->
<script lang="ts">
  import { ParticleEmitter } from 'pixi-svelte';
  import type { EmitterConfigV3 } from '@barvynkoa/particle-emitter';

  let emitting = $state(false);

  const config: EmitterConfigV3 = {
    lifetime: { min: 0.4, max: 0.9 },
    frequency: 0.01,
    spawnChance: 1,
    maxParticles: 80,
    pos: { x: 0, y: 0 },
    addAtBack: false,
    behaviors: [
      {
        type: 'alpha',
        config: { alpha: { list: [{ value: 1, time: 0 }, { value: 0, time: 1 }] } },
      },
      {
        type: 'scale',
        config: { scale: { list: [{ value: 0.8, time: 0 }, { value: 0.1, time: 1 }] } },
      },
      {
        type: 'moveSpeed',
        config: { speed: { list: [{ value: 300, time: 0 }, { value: 50, time: 1 }] } },
      },
      {
        type: 'spawnShape',
        config: { type: 'torus', data: { x: 0, y: 0, radius: 5 } },
      },
    ],
  };
</script>

<Container x={400} y={300}>
  <ParticleEmitter key="sparks" {config} emit={emitting} />
</Container>

<ParticleContainer>

A wrapper around PIXI.ParticleContainer that provides the particle parent context to child <Particles> components. More performant than a regular <Container> for large numbers of identical sprites.

Props

children
Snippet
required
One or more <Particles> components.
dynamicProperties
Partial<PIXI.ParticleContainerProperties>
An object specifying which properties (vertices, position, rotation, uvs, tint) are updated per particle. Enabling more properties increases GPU upload cost. From PIXI.ParticleContainerOptions.
maxSize
number
Maximum number of particles. Must be set at creation time. From PIXI.ParticleContainerOptions.
batchSize
number
Number of particles per draw call batch. From PIXI.ParticleContainerOptions.
autoResize
boolean
Whether the container automatically resizes to accommodate more particles than maxSize. From PIXI.ParticleContainerOptions.
x
number
Horizontal position. Default 0.
y
number
Vertical position. Default 0.
alpha
number
Opacity. Default 1.
visible
boolean
Whether the container is rendered. Default true.
zIndex
number
Sort order within the parent. Default 0.
cursor
Cursor
CSS cursor string.

<Particles>

A low-level particle layer. Creates size PIXI.Particle instances using a texture resolved from stateApp.loadedAssets, calls init once on mount, and calls update on every PixiJS ticker tick. Must be a child of <ParticleContainer>.

Props

key
string
required
Asset manifest key for a sprite asset. The loaded texture is applied to every particle instance.
size
number
required
The number of PIXI.Particle instances to create.
init
(particles: PIXI.Particle[]) => void
required
Called once after the particles are created. Set initial positions, scales, alphas, velocities, etc.
update
(particles: PIXI.Particle[]) => void
required
Called every frame via the PixiJS ticker. Mutate each particle’s properties to simulate motion, fade, etc. The ParticleContainer is updated automatically after this callback.

Example

<!-- Asset manifest: star: { type: 'sprite', src: '/images/star.png' } -->
<script lang="ts">
  import { ParticleContainer, Particles } from 'pixi-svelte';
  import * as PIXI from 'pixi.js';

  type ParticleState = { vx: number; vy: number };
  const states: ParticleState[] = [];

  function init(particles: PIXI.Particle[]) {
    particles.forEach((p, i) => {
      p.x = Math.random() * 800;
      p.y = Math.random() * 600;
      p.scale.set(Math.random() * 0.5 + 0.2);
      p.alpha = Math.random();
      states[i] = {
        vx: (Math.random() - 0.5) * 2,
        vy: (Math.random() - 0.5) * 2,
      };
    });
  }

  function update(particles: PIXI.Particle[]) {
    particles.forEach((p, i) => {
      p.x += states[i].vx;
      p.y += states[i].vy;
      if (p.x > 800) p.x = 0;
      if (p.y > 600) p.y = 0;
    });
  }
</script>

<ParticleContainer>
  <Particles key="star" size={200} {init} {update} />
</ParticleContainer>
<Particles> adds particles to the ParticleContainer at mount time and never removes them. To hide unused particles, set alpha = 0 in your update function rather than removing them.

Build docs developers (and LLMs) love