JSPM

  • Created
  • Published
  • Downloads 226
  • Score
    100M100P100Q99449F
  • License MIT

A high-performance WebGL cascading reel animator for slot-style UIs on any HTMLCanvasElement

Package Exports

  • cascading-reel
  • cascading-reel/dist/index.cjs.js
  • cascading-reel/dist/index.cjs.js.map
  • cascading-reel/dist/index.d.ts
  • cascading-reel/dist/index.es.js
  • cascading-reel/dist/index.es.js.map
  • cascading-reel/dist/index.umd.js
  • cascading-reel/dist/index.umd.js.map

Readme

cascading-reel

A high-performance WebGL cascading reel animator for slot-style UIs on any HTMLCanvasElement.

  • 3x3 reel grid with deterministic scripted outcomes.
  • Queued spins with per-spin callbacks.
  • Win highlight with electric border and particle burst.
  • DPR-aware rendering for mobile and desktop.

Install

yarn add cascading-reel

Usage (TypeScript)

import { CascadingReel } from 'cascading-reel';

const container = document.getElementById('reelWrap');
const canvas = document.getElementById('canvas');
const button = document.getElementById('spinBtn');

if (!container || !canvas || !button) {
  throw new Error('Demo DOM is not ready');
}

const reel = new CascadingReel({
  container: container as HTMLDivElement,
  canvas: canvas as HTMLCanvasElement,
  button: button as HTMLButtonElement,
  sprite: new URL('./assets/reel.webp', import.meta.url).href,
  spriteElementsCount: 6,
  initialSegments: [
    [0, 1, 2],
    [3, 0, 5],
    [0, 1, 0],
  ],
  queuedSpinStates: [
    {
      stopRows: [
        [0, 4, 5],
        [2, 1, 4],
        [1, 3, 0],
      ],
      finaleSequenceRows: [
        [
          [1, 1, 0],
          [0, 1, 2],
          [4, 5, 1],
        ],
      ],
      highlightWin: true,
      callback: () => console.log('spin complete'),
    },
  ],
});

await reel.init();
reel.spin();

Usage (Vue 3)

<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
import { CascadingReel } from 'cascading-reel';

const containerRef = ref<HTMLDivElement | null>(null);
const canvasRef = ref<HTMLCanvasElement | null>(null);
const buttonRef = ref<HTMLButtonElement | null>(null);
const reel = shallowRef<CascadingReel | null>(null);

onMounted(async () => {
  if (!containerRef.value || !canvasRef.value) return;
  reel.value = new CascadingReel({
    container: containerRef.value,
    canvas: canvasRef.value,
    button: buttonRef.value ?? undefined,
    sprite: new URL('./assets/reel.webp', import.meta.url).href,
    spriteElementsCount: 6,
    particleColor: 'rainbow',
  });
  await reel.value.init();
});

onBeforeUnmount(() => {
  reel.value?.destroy();
  reel.value = null;
});
</script>

<template>
  <button ref="buttonRef">Spin</button>
  <div ref="containerRef">
    <canvas ref="canvasRef"></canvas>
  </div>
</template>

HTML Layout

<button id="spinBtn">Spin</button>
<div id="reelWrap">
  <canvas id="canvas"></canvas>
</div>

Call reel.spin() to consume the next item from queuedSpinStates.

SpinState

type SpinState = {
  stopGrid?: number[][];
  stopRows?: number[][];
  finaleSequence?: number[][][];
  finaleSequenceRows?: number[][][];
  highlightWin?: boolean;
  callback?: () => void;
};
  • Use stopRows for row-major input ([row][col]).
  • Use stopGrid for column-major input ([col][row]).
  • finaleSequenceRows and finaleSequence follow the same row/column conventions.

Options

Option Type Default Description
canvas HTMLCanvasElement Canvas for rendering.
container HTMLElement Element used for responsive sizing.
button HTMLButtonElement Optional spin button.
sprite string Sprite sheet URL.
spriteElementsCount number 6 Number of symbols in the sprite sheet.
initialSegments number[][] randomized Initial 3x3 state in rows format.
highlightInitialWinningCells boolean true Show initial highlight before first spin.
queuedSpinStates SpinState[] [] Predefined queue consumed by spin().
particleColor 'rainbow' | [number, number, number] [255, 235, 110] Win particle color mode or solid RGB color.

Methods

await reel.init();
reel.spin();
reel.destroy();

Sprite Format

  • Single vertical sprite sheet.
  • Every symbol frame is square.
  • Total texture height equals spriteElementsCount * frameWidth (square-frame assumption).
  • PNG and WebP with transparency are supported.

License

MIT