Vanilla Disintegratev1.3.0
EN
On this page

The built-in particle renderer is available from the root, /snapdom, and /particles entry points. Import /particles when you need only the renderer and its types, without Disintegrator, capture, or bundled audio.

import {
  configureParticleContexts,
  createParticleAnimation,
  createParticleEffect,
  createParticleRestoreAnimation,
  particlePresets,
} from 'vanilla-disintegrate/particles';

createParticleEffect(options?)

Creates a complete EffectDefinition with independent remove and restore phases.

interface ParticleEffectOptions {
  remove?: ParticleOptions;
  restore?: ParticleOptions;
}

const effect = createParticleEffect({
  remove: { ...particlePresets.vapor, release: 'top' },
  restore: { ...particlePresets.scatter, release: 'center' },
});

When restore is omitted, it uses the same options as remove. When both fields are omitted, both phases use the particle defaults. The factory configures visuals only; add sound separately or wrap the effect and audio in a complete preset.

ParticleOptions

Distances and particle sizes are expressed in CSS pixels, durations in milliseconds, rotation in degrees, and normalized controls in the 01 range.

OptionTypeDefaultWhat it controls
renderQuality'auto' | 'exact' | ParticleRenderBudget'auto'Resolution and resource limits of the WebGL renderer
particleSize'auto' | number'auto'Minimum edge length of one particle; numeric values are clamped to at least 0.25
alphaThresholdnumber0Source pixels at or below this alpha value do not create particles
curve'settle' | 'float' | 'burst' | 'drift''settle'Travel, acceleration, and restoration profile
durationnumber720Base duration of the phase
staggernumber180Maximum additional start delay distributed across particles
release'left' | 'right' | 'top' | 'bottom' | 'center' | 'edges' | 'random''left'Region of the element that releases first
releaseRandomnessnumber0.22Mix between the selected release order (0) and random order (1)
fadeStartnumberDepends on curvePoint in each particle’s local lifetime where fading begins
layoutReleasenumber0.6Fraction of particles that must be released before surrounding layout moves
horizontalDriftnumber42Random sideways variation added to each path
horizontalTravelreadonly [number, number][0, 0]Minimum and maximum directed horizontal travel
verticalTravelreadonly [number, number][-100, -45]Minimum and maximum vertical travel; negative values move upward
convergencenumber0Pull toward the horizontal centre of the element
swirlnumber0Amplitude of the vertical wave along a path
waveTurnsnumberDepends on curveNumber of oscillations along a path
endScalenumber0.92Particle scale at the end of removal
rotationreadonly [number, number][0, 0]Minimum and maximum terminal rotation assigned to particles

alphaThreshold, convergence, releaseRandomness, fadeStart, and layoutRelease are clamped to 01. Negative duration, stagger, horizontalDrift, swirl, waveTurns, and endScale values are clamped to zero. Reversed range endpoints are sorted automatically.

Curves

CurveCharacterDefault fadeStartDefault waveTurns
settleBalanced movement with a smooth finish0.31
floatSofter floating movement0.31.6
burstFaster initial acceleration0.121
driftLong directional movement0.321.25

Explicit fadeStart and waveTurns values override the curve defaults.

Release order

left, right, top, and bottom release particles from the named edge. center starts near the centre and moves outward; edges starts at the outside and moves inward. random has no geometric order. releaseRandomness can soften any ordered pattern without changing the selected direction.

Layout handoff

layoutRelease determines when the DOM reflow animation begins during removal. A value of 0 allows layout to move immediately; 1 waits until every particle has been released. The renderer calculates the actual layoutDelay from the generated particle field, so it remains aligned with release and releaseRandomness.

Render quality

type ParticleRenderQuality = 'auto' | 'exact' | ParticleRenderBudget;

interface ParticleRenderBudget {
  maxSourcePixels: number;
  maxSourceDimension: number;
  maxRenderPixels: number;
}

auto uses the following software limits:

{
  maxSourcePixels: 2_000_000,
  maxSourceDimension: 2048,
  maxRenderPixels: 4_000_000,
}

exact preserves the capture’s full resolution and disables software downscaling. It cannot exceed the device’s WebGL texture or viewport limits; an unsupported surface is reported through onError. A custom budget lets an application choose its own balance between sharpness, memory, and GPU work.

renderQuality affects only the WebGL renderer. The capture adapter independently decides how many pixels are present in the source canvas.

Low-level phase factories

function createParticleAnimation(options?: ParticleOptions): AnimationFactory;
function createParticleRestoreAnimation(options?: ParticleOptions): AnimationFactory;

createParticleAnimation() creates a remove-phase animation factory. createParticleRestoreAnimation() creates the corresponding restore-phase factory. Use them when composing an EffectDefinition manually; prefer createParticleEffect() when both phases use the built-in renderer.

Both factories require a snapshot. If their AnimationContext.snapshot is null, they return null, causing the operation to follow the normal skipped-animation fallback.

particlePresets

type BuiltInPreset = 'dust' | 'scatter' | 'vapor' | 'wind';

const particlePresets: Readonly<Record<BuiltInPreset, Readonly<ParticlePreset>>>;

particlePresets contains deeply frozen visual configurations only. They do not include audio and are intended for createParticleEffect() or the low-level factories. builtInPresets, exported by the root and /snapdom entries, are complete visual-and-audio presets for Disintegrator.

configureParticleContexts(limits?)

interface ParticleContextLimits {
  maxContexts?: number;
  maxIdleContexts?: number;
}

const applied = configureParticleContexts({
  maxContexts: 2,
  maxIdleContexts: 1,
});

The setting is page-wide and should normally be applied once before an effect starts. The defaults keep at most four live WebGL2 contexts and at most two idle contexts for reuse. Idle contexts are released after 30 seconds; contexts above the idle limit are released immediately.

maxContexts is normalized to an integer of at least 1. maxIdleContexts is normalized to a non-negative integer and cannot exceed maxContexts. The function returns the limits currently in use.

If the renderer cannot acquire a context, the DOM operation still commits, finished resolves with status: 'skipped', and the failure is reported through onError.

Edit this page on GitHub