particles#
Deterministic, stateless particle systems. Every particle's position, size, rotation, and color is a pure function of (element id, particle index, age) — which means seeking backward or jumping to a frame works without resimulating from the start. A Clipkit extension. Inherits common fields .
interface ParticlesElement extends BaseElement {
type : "tok-str" >'particles';
rate?: number;
lifetime?: number;
velocity?: number;
spread?: number;
direction?: number;
gravity?: number;
color?: string | string[];
size?: number;
size_variation?: number;
particle_shape?: "tok-str" >'square' | "tok-str" >'circle';
rotation_speed?: number;
burst?: boolean;
burst_count?: number;
fade_at?: number;
z_velocity?: number;
z_spread?: number;
"tok-cmt" >// Convergence mode
target_points?: [number, number][];
convergence_easing?: EasingFunction;
scatter_radius?: number;
}
Two modes#
The element runs in one of two modes:
Ballistic (default) — particles emit from the element's (x, y), given a random initial velocity, and fall under gravity. Use for confetti, sparks, snow, dust.
Convergence — set target_points. Particles interpolate from random scattered start positions toward those points over their lifetime. Use for "particles assemble into a logo" effects.
Emission#
Field Type Default Description ratenumber60Particles per second (continuous mode). burstbooleanfalseIf true, emit burst_count particles instantly at element start instead of continuously. burst_countnumber80Number of particles in a burst. lifetimenumber1.5Lifetime per particle, in seconds. fade_atnumber0.7Fraction of lifetime at which particles start fading out. 1 = no fade.
Motion (ballistic mode)#
Field Type Default Description velocitynumber300Initial speed in px/s. Actual speed is velocity × (1 ± 0.3 × random). spreadnumber360Spread cone in degrees. 0 = directional (everyone moves the same way); 360 = omnidirectional. directionnumber-90Emission direction in degrees. 0° = right; 90° = down; -90° = up. gravitynumber600Vertical acceleration in px/s². Positive = downward. rotation_speednumber360Rotation rate in deg/s. Sign is randomized per particle. z_velocitynumber0Depth speed in px/s along the plane normal. Drives particles toward/away from the camera (2.5D). z_spreadnumber0Random depth-speed range in px/s. Each particle's z-velocity is z_velocity ± z_spread × random.
Motion (convergence mode)#
Field Type Default Description target_points[number, number][]— Target positions in canvas pixel coordinates. Particles are assigned round-robin to these points by index. When set, motion fields above (velocity, gravity, etc.) are ignored. convergence_easingEasingFunction'ease-out-quart'Easing applied to the convergence interpolation. scatter_radiusnumbermax(canvas_width, canvas_height)Radius of the random scatter region around the emitter where particles start.
Appearance#
Field Type Default Description colorstring | string[]'#ffffff'Hex color, or an array for per-particle randomization (uniform). sizenumber12Mean particle size in pixels. size_variationnumber0.4Random size variation in [0, 1]. 0 = all uniform; 1 = sizes anywhere in [0, size]. particle_shape'square' | 'circle''square'Per-particle shape.
Example: confetti burst#
{
"type" : "particles" ,
"id" : "celebrate" ,
"layer" : 1 ,
"x" : 960 , "y" : 540 ,
"time" : 3 ,
"duration" : 2 ,
"burst" : true ,
"burst_count" : 200 ,
"lifetime" : 2 ,
"velocity" : 800 ,
"spread" : 180 ,
"direction" : -90 ,
"gravity" : 800 ,
"rotation_speed" : 540 ,
"size" : 14 ,
"size_variation" : 0.6 ,
"color" : [ "#ef4444" , "#facc15" , "#22c55e" , "#3b82f6" , "#a855f7" ]
}
Example: logo convergence#
Pair with SVGPathElement.getPointAtLength() ahead of time to pre-sample N points along your logo's outline, then:
{
"type" : "particles" ,
"id" : "assemble" ,
"layer" : 1 ,
"x" : 960 , "y" : 540 ,
"time" : 0 ,
"duration" : 2 ,
"burst" : true ,
"burst_count" : 120 ,
"lifetime" : 1.6 ,
"fade_at" : 1 ,
"color" : "#facc15" ,
"size" : 6 ,
"size_variation" : 0.2 ,
"particle_shape" : "circle" ,
"convergence_easing" : "ease-out-quart" ,
"target_points" : [
[ 860 , 480 ] , [ 880 , 480 ] , [ 900 , 480 ]
/* ... 117 more, sampled from your logo path ... */
]
}
Notes#
Deterministic — particles use a seeded PRNG keyed off (element id, particle index). The same Source renders identically every time.
No collisions — there is no inter-particle physics. Each particle is independent.
No emitters-over-time — the element has one continuous emitter or one burst. For multiple bursts, use multiple particles elements.