Help guide

Physics Body Stagger node

Updated June 21, 2026

Physics Body Stagger node

Product media placeholder

Replace this area with a screenshot or short walkthrough video during the media sweep.

Runtime-fanout compound — one node = N physicsBody instances + N DOM transform writes. Resolves N elements at bind time from a plain CSS selector and creates one body per element with shared params. Per-element radius via `shape.radiusFromCSS: "--bd"` reads each element's CSS variable (same convention `staggerAnimate` uses). Saves ~3N nodes for ball-drop / scatter patterns. For per-element heterogeneity beyond size (different bodyKind / restitution per element), drop down to primitive `physicsBody` + `domPoseWrite` pairs.

Type physicsBodyStaggerCategory solversContext sharedDynamic ports noCompound no

Inputs

PortTypeDescription
worldanyWire to the sibling `physicsWorld.world` output. Loader resolves at bind and registers all N bodies in this world.
enabledfloatWhen 0, all N bodies removed from broadphase (frozen at last pose).
progressfloatOptional 0..1 driver. When wired AND `resetBelowProgress` param is set, every body re-snaps to its initial pose + zero velocity on the falling edge of progress crossing the threshold (i.e. when scrolling BACK up past the trigger). For the dental ball-drop pattern: pair with `physicsWorld.pauseBelowProgress` set to the same threshold.
targetCenterXfloatIK-style target. When wired, overrides authored `initialX` so balls spawn centered on the wired source — typically `physicsStaticBody.centerX`. Eliminates the "two-vh-values out of sync" failure mode where the cup is at one viewport position and balls spawn at another.
targetTopYfloatIK-style target. When wired, overrides authored `initialY`. Spawn Y = targetTopY + targetTopOffset, so a small negative offset (e.g. -50px) drops balls in from just above the cup mouth.
targetTopOffsetfloatPixel offset added to `targetTopY` to compute spawn Y. Negative = above the cup mouth (default `-50`). Use to tune drop height without recomputing the cup geometry.
targetMouthWidthfloatWidth of the target's mouth — wire from `physicsStaticBody.mouthWidth`. Drives `spawnPattern: "fanFromMouth"` to evenly distribute N balls across the mouth without hand-tuning per-ball spacing.

Outputs

PortTypeDescription
bodyIdsfloatArrayPer-element engine handle in match order. Wire to v2 `physicsApplyImpulse[index]` / `physicsCollisionPulse[index]` to address one specific ball inside the stagger.
countfloatNumber of elements matched + bodies created. Useful for downstream `expression` / `arrayPick` consumers.

Parameters

ParameterTypeDefaultDescription
selectorelementSelector""CSS selector matching N sibling elements (e.g. `".wu-ball"`). One body created per match in document order.
shapephysicsShape{"kind":"circle","radius":25}Shared shape across all N bodies. For circles, set `radiusFromCSS: "--bd"` to read each element's --bd CSS var as the diameter (halved internally for radius). Same per-element convention `staggerAnimate` uses.
initialXstring0Spawn X position (CSS units like "20vw" supported). Combine with `initialXSpacing` for evenly spaced fan-out.
initialYstring0Spawn Y position. Negative values like "-25vh" spawn balls above the viewport.
initialXSpacingfloat0Adds `index * spacingPx` to each body's initial X. 0 = all at same X (jitter handles separation if non-zero). step 10
initialYSpacingfloat0Y Spacing per Index (px) step 10
jitterXfloat0Per-index deterministic hash → ±jitterX px on initial X. Same hash on rebind so balls land at the same spots. min 0; step 10
jitterYfloat0Per-index deterministic hash → ±jitterY px on initial Y. Same hash on rebind so balls land at the same spots. min 0; step 10
densityfloat1Mass per unit area, applied to every ball. Lower = lighter (more bouncy / easier to push); higher = heavier (more momentum). min 0.001; step 0.1
restitutionfloat0.50 = no bounce, 1 = perfectly elastic, > 1 = energy-amplifying. Applied to every ball. min 0; max 2; step 0.05
frictionfloat0.5Surface friction coefficient on every ball. 0 = ice (slides forever), 1 = typical solid. min 0; max 2; step 0.05
linearDampingfloat0Per-second exponential damping on linear velocity for every ball. Higher = settles faster. min 0; step 0.05
angularDampingfloat0Per-second exponential damping on angular velocity for every ball. min 0; step 0.05
lockRotationboolfalseWhen true, balls cannot rotate (locks angular DOF). Useful when ball labels need to stay upright.
ccdboolfalseContinuous Collision Detection on every ball. Enables tunnelling-prevention for fast falls / small balls. Costs slightly more CPU.
writeTransformenumtrueHow the node writes per-frame body pose to each element. `Transform` (default) sets `style.transform = translate(x,y) rotate(r)` directly — fast, simple, but overwrites any inherited transform. Use `CSS Var` when bodies live INSIDE a transformed parent (carousel slot, scroll-pinned stage, FLIP layout) — author-CSS composes via `transform: translate(var(--phys-x), var(--phys-y)) rotate(var(--phys-r))` so the parent transform stays intact. `None` writes nothing; consume `bodyIds` and route to a custom DOM write chain. Legacy boolean values (`true` / `false`) are still accepted in JSON. options transform, cssVar, none
resetBelowProgressfloatnullFalling-edge reset gate. When set (e.g. 0.75), every body re-snaps to its initial pose + zero velocity the frame `progress` drops below this threshold — fires once on scroll-up past the trigger, then the world stays paused (pair with physicsWorld.pauseBelowProgress at the same value). Leave blank to never reset; balls remain wherever they last fell. min 0; max 1; step 0.05
spawnPatternenum"explicit"Selects how the per-element X offset is computed. "explicit" uses the legacy `i * initialXSpacing` math. "fanFromMouth" reads the wired `targetMouthWidth` and the live element count, fanning N balls evenly across the mouth — `initialXSpacing` is ignored. Falls back to "explicit" when `targetMouthWidth` is unwired. options explicit, fanFromMouth

Use cases

  • Dental ball-drop — one stagger node creates 6 dynamic circles from `.wu-ball` siblings, each with its own radius via `--bd`. Replaces 6 physicsBody + 6 domPoseWrite nodes (12 → 1).
  • Scatter / confetti — N badges fall under gravity into a target area. Authors set spawn jitter via `jitterX` / `jitterY` for organic randomness (deterministic per-index hash, no Math.random).
  • Marble run — N marbles stream from above, hit static path colliders, settle. Stagger handles all N marbles uniformly; per-marble params come from CSS vars.

Related nodes

Envelope

Use physicsBodyStagger as the node type inside a graph node envelope. Add id, optional params, optional connections, and optional activeWhen based on the guide context.

Generated source

Registry faster-motion-docs/node-registry.jsonCategory page /help/faster-motion/faster-motion-node-category-solvers/

Was this guide helpful?

Sunny Arora

Written by

Sunny Arora

Get technical deep dives delivered to your inbox

Join creators and developers who get exclusive insights, tutorials, and behind-the-scenes content every week.

No spam. Unsubscribe anytime.

Continue Exploring

You might also enjoy