Every event pixi-reels emits is typed. The headline stream comes off
reelSet.events. Each Reel also has its own
per-reel stream — useful when you want to drive behavior on one column
without the whole set.
The spin timeline
A typical spin unfolds in this exact order. The timeline below has the reel-set-level events on the top track and per-reel events on the bottom. Read left-to-right as wall-clock time.
The full event map
| Event | Payload | Fires when |
|---|---|---|
| spin:start | — | Any spin() call |
| spin:allStarted | — | Every reel is in SPIN phase |
| spin:stopping | reelIndex | A reel begins STOP (or ANTICIPATION) |
| spin:reelLanded | reelIndex, symbols[] | A reel finished landing |
| spin:allLanded | result: SpinResult | Last reel landed |
| spin:complete | result: SpinResult | Just after spin:allLanded |
| skip:requested | — | skip() called |
| skip:completed | — | All reels force-landed |
| speed:changed | profile, previous | setSpeed() called |
| spotlight:start | positions: SymbolPosition[] | spotlight.cycle(...) began |
| spotlight:end | — | Spotlight sequence finished |
| destroyed | — | destroy() called |
Two interaction patterns
Wiring these events together gets you every major slot UX without custom state tracking:
Use isSpinning to branch the same button between "start" and "slam-stop."
button.addEventListener('click', () => {
if (reelSet.isSpinning) reelSet.skip();
else reelSet.spin();
}); Real slots fetch the server answer while the reels are spinning, then call setResult() to trigger the stop.
const p = reelSet.spin();
const r = await fetch('/spin').then(x => x.json());
reelSet.setAnticipation(r.anticipationReels);
reelSet.setResult(r.symbols);
await p; Listening on a single reel
Each Reel has its own typed emitter. Useful when only one
column's state matters — e.g. a sticky wild tracker that needs to
know exactly when reel 2 landed:
reelSet.getReel(2).events.on('landed', (symbols) => {
if (symbols.includes('wild')) stickyWilds.push({ reel: 2, ... });
});