PR pixi-reels
All recipes

Tumble feels. every preset, side by side

Five interactive canvases, same spin + cascade-refill loop. Only the .tumble({ fall, dropIn }) config changes between them. Click each SPIN to compare the feel without writing a line of code.

Every canvas below runs the exact same scripted spin: 6×4 cards land with a pre-wired 3-cluster of 10 on row 2, those three winners fade out, the loop pauses for a configured beat, then the cascade refill drops survivors into the holes and brings a fresh row from above. Two things vary between canvases:

  1. .tumble({ fall, dropIn }). the animation feel itself.
  2. PAUSE_AFTER_REMOVAL_MS. the breathing room between the win-fade and the refill drop-in. Different feels want different pauses: snappy slams want ~120 ms, bouncy / dramatic feels want ~300-400 ms. Each canvas’s value is tuned to match its tumble shape.

Classic. the all-rounder default

Loading recipe…

.tumble({
  fall:   { duration: 280, ease: 'sine.in',       rowStagger: 40 },
  dropIn: { duration: 480, ease: 'back.out(1.6)', rowStagger: 50, distance: 'perHole' },
})

Gentle gravity fall + soft overshoot landing. back.out(1.6) overshoots its target by ~60 % and settles. Start here; tweak from here. A reasonable default if you have no other constraints.

Cartoon bounce. multi-bounce settle

Loading recipe…

.tumble({
  fall:   { duration: 320, ease: 'sine.in',    rowStagger: 60 },
  dropIn: { duration: 700, ease: 'bounce.out', rowStagger: 70, distance: 'perHole' },
})

bounce.out does a real multi-bounce settle. Symbols actually bounce on landing. Longer durations (700 ms) let each bounce read. Be careful with this one on dense grids: the bouncing arrival overlaps the next phase visually and can slow the perceived pace.

Slam. hard-landing, sub-half-second tumble

Loading recipe…

.tumble({
  fall:   { duration: 180, ease: 'power4.in', rowStagger: 20 },
  dropIn: { duration: 260, ease: 'expo.out',  rowStagger: 25, distance: 'perHole' },
})

power4.in accelerates the fall steeply (heavy, gravity-like). expo.out lands hard with no overshoot. The whole tumble plays in under half a second. A reasonable basis for a turbo mode toggle on top of a default-classic build.

Rain column. board-falls-as-a-slab

Loading recipe…

.tumble({
  fall:   { duration: 240, ease: 'sine.in', rowStagger: 0 },
  dropIn: { duration: 380, ease: 'sine.in', rowStagger: 0, distance: 'auto' },
})

rowStagger: 0 makes every row start together. distance: 'auto' overrides the gravity-correct per-hole distance with a uniform full-column-height drop, so the new column appears as a coherent slab from above the viewport. Match-3, puzzle, or chess-board grids where “the board itself moves” is the visual idea.

Wave. rolling top-to-bottom reveal

Loading recipe…

.tumble({
  fall:   { duration: 180, ease: 'sine.in',       rowStagger: 90 },
  dropIn: { duration: 320, ease: 'back.out(2.0)', rowStagger: 110, distance: 'perHole' },
})

Heavy rowStagger (110 ms on drop-in) makes each row land in its own beat. back.out(2.0) adds a stronger overshoot than Classic. Row 0 lands, then row 1, then row 2. Pair with row-by-row sound cues if you want a per-row audio hit. The more cascades in a chain, the more rows arrive in sequence.

Picking between them

FeelPausePick whenAvoid when
Classic250 msDefault if you have no other constraints.
Cartoon bounce320 msSoft overshoot, multi-bounce landingDense grids where the bounce overlaps the next phase
Slam120 msTurbo mode, sub-half-second tumblesYou want a longer beat between cascades
Rain column380 msMatch-3 / chess-board / puzzle gridsReels are visually distinct (the cohesive slab look fights the column gaps)
Wave280 msStrong per-row stagger, row-by-row arrivalVery dense grids. the stagger makes the whole tumble feel long

The Pause column is PAUSE_AFTER_REMOVAL_MS in each recipe. the gap between the win-fade ending and the refill drop-in starting. It’s not a library setting; it’s just an await wait(ms) in your spin loop. Tuning it per feel is the single biggest lever on cascade pacing after the tumble config itself.

Beyond these five: anything goes. ease accepts any GSAP easing string. rowStagger is plain ms. distance is 'perHole' / 'auto' / a number. Mix to taste; the algorithm and lifecycle stay exactly the same.

Going beyond config

If a feel needs effects the config can’t express (squish, sticky badge tweens, spine state transitions, particle bursts). those are events, not config fields. Subscribe to cascade:fall:symbol / cascade:dropIn:symbol and run parallel tweens on any view property; they fire before the library’s view.y tween so your tweens stay in sync.

See the full tumble recipe doc for the per-symbol event hooks, the cascading-multiplier pattern, and the phase-override escape hatch.