Events
What fires when, and in what order.
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.
sequenceDiagram participant Caller participant ReelSet participant Reel as Reel (per-reel) Note over Caller,Reel: START phase Caller->>ReelSet: spin() ReelSet-->>Caller: spin:start ReelSet->>Reel: phase:enter "start" Note over Caller,Reel: SPIN phase Reel-->>Caller: phase:exit "start" Reel-->>Caller: phase:enter "spin" ReelSet-->>Caller: spin:allStarted Reel-->>Caller: symbol:created (many) Caller->>ReelSet: setResult(symbols[][]) Caller->>ReelSet: setAnticipation([3,4]) Note over Caller,Reel: ANTICIPATION phase (optional) Reel-->>Caller: phase:exit "spin" Reel-->>Caller: phase:enter "anticipation" Note over Caller,Reel: STOP phase ReelSet-->>Caller: spin:stopping (per reel) Reel-->>Caller: phase:enter "stop" Note over Caller,Reel: LANDED Reel-->>Caller: phase:exit "stop" Reel-->>Caller: landed (symbols[]) ReelSet-->>Caller: spin:reelLanded (per reel) ReelSet-->>Caller: spin:allLanded ReelSet-->>Caller: spin:complete
The full event map
| Event | Payload | Fires when |
|---|---|---|
| spin:start | (none) | Any spin() call |
| spin:allStarted | (none) | 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 | (none) | skipSpin() called |
| skip:completed | (none) | All reels force-landed |
| speed:changed | profile, previous | setSpeed() called |
| spotlight:start | positions: SymbolPosition[] | spotlight.cycle(...) began |
| spotlight:end | (none) | Spotlight sequence finished |
| destroyed | (none) | 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.skipSpin();
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, ... });
});