cascading-reel 1.0.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,169 +1,169 @@
1
- # cascading-reel
2
-
3
- A high-performance WebGL cascading reel animator for slot-style UIs on any `HTMLCanvasElement`.
4
-
5
- - 3x3 reel grid with deterministic scripted outcomes.
6
- - Queued spins with per-spin callbacks.
7
- - Win highlight with electric border and particle burst.
8
- - DPR-aware rendering for mobile and desktop.
9
-
10
- ## Install
11
-
12
- ```bash
13
- yarn add cascading-reel
14
- ```
15
-
16
- ## Usage (TypeScript)
17
-
18
- ```ts
19
- import { CascadingReel } from 'cascading-reel';
20
-
21
- const container = document.getElementById('reelWrap');
22
- const canvas = document.getElementById('canvas');
23
- const button = document.getElementById('spinBtn');
24
-
25
- if (!container || !canvas || !button) {
26
- throw new Error('Demo DOM is not ready');
27
- }
28
-
29
- const reel = new CascadingReel({
30
- container: container as HTMLDivElement,
31
- canvas: canvas as HTMLCanvasElement,
32
- button: button as HTMLButtonElement,
33
- sprite: new URL('./assets/reel.webp', import.meta.url).href,
34
- spriteCrossOrigin: 'anonymous',
35
- spriteElementsCount: 6,
36
- symbolScale: 0.85,
37
- initialSegments: [
38
- [0, 1, 2],
39
- [3, 0, 5],
40
- [0, 1, 0],
41
- ],
42
- queuedSpinStates: [
43
- {
44
- stopRows: [
45
- [0, 4, 5],
46
- [2, 1, 4],
47
- [1, 3, 0],
48
- ],
49
- finaleSequenceRows: [
50
- [
51
- [1, 1, 0],
52
- [0, 1, 2],
53
- [4, 5, 1],
54
- ],
55
- ],
56
- highlightWin: true,
57
- callback: () => console.log('spin complete'),
58
- },
59
- ],
60
- });
61
-
62
- await reel.init();
63
- reel.spin();
64
- ```
65
-
66
- ## Usage (Vue 3)
67
-
68
- ```vue
69
- <script setup lang="ts">
70
- import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
71
- import { CascadingReel } from 'cascading-reel';
72
-
73
- const containerRef = ref<HTMLDivElement | null>(null);
74
- const canvasRef = ref<HTMLCanvasElement | null>(null);
75
- const buttonRef = ref<HTMLButtonElement | null>(null);
76
- const reel = shallowRef<CascadingReel | null>(null);
77
-
78
- onMounted(async () => {
79
- if (!containerRef.value || !canvasRef.value) return;
80
- reel.value = new CascadingReel({
81
- container: containerRef.value,
82
- canvas: canvasRef.value,
83
- button: buttonRef.value ?? undefined,
84
- sprite: new URL('./assets/reel.webp', import.meta.url).href,
85
- spriteCrossOrigin: 'anonymous',
86
- spriteElementsCount: 6,
87
- symbolScale: 0.85,
88
- particleColor: 'rainbow',
89
- });
90
- await reel.value.init();
91
- });
92
-
93
- onBeforeUnmount(() => {
94
- reel.value?.destroy();
95
- reel.value = null;
96
- });
97
- </script>
98
-
99
- <template>
100
- <button ref="buttonRef">Spin</button>
101
- <div ref="containerRef">
102
- <canvas ref="canvasRef"></canvas>
103
- </div>
104
- </template>
105
- ```
106
-
107
- ## HTML Layout
108
-
109
- ```html
110
- <button id="spinBtn">Spin</button>
111
- <div id="reelWrap">
112
- <canvas id="canvas"></canvas>
113
- </div>
114
- ```
115
-
116
- Call `reel.spin()` to consume the next item from `queuedSpinStates`.
117
-
118
- ## SpinState
119
-
120
- ```ts
121
- type SpinState = {
122
- stopGrid?: number[][];
123
- stopRows?: number[][];
124
- finaleSequence?: number[][][];
125
- finaleSequenceRows?: number[][][];
126
- highlightWin?: boolean;
127
- callback?: () => void;
128
- };
129
- ```
130
-
131
- - Use `stopRows` for row-major input (`[row][col]`).
132
- - Use `stopGrid` for column-major input (`[col][row]`).
133
- - `finaleSequenceRows` and `finaleSequence` follow the same row/column conventions.
134
-
135
- ## Options
136
-
137
- | Option | Type | Default | Description |
138
- |:-------------------------------|:-----------------------------------------|:-----------------:|:-------------------------------------------------------|
139
- | `canvas` | `HTMLCanvasElement` | — | Canvas for rendering. |
140
- | `container` | `HTMLElement` | — | Element used for responsive sizing. |
141
- | `button` | `HTMLButtonElement` | — | Optional spin button. |
142
- | `sprite` | `string \| HTMLImageElement` | — | Sprite sheet URL or preloaded image element. |
143
- | `spriteCrossOrigin` | `'' \| 'anonymous' \| 'use-credentials'` | `'anonymous'` | `crossOrigin` mode used when `sprite` is a URL string. |
144
- | `spriteElementsCount` | `number` | `6` | Number of symbols in the sprite sheet. |
145
- | `symbolScale` | `number` | `0.9` | Symbol scale inside the cell. Clamped to `0.5..1.2`. |
146
- | `initialSegments` | `number[][]` | randomized | Initial 3x3 state in rows format. |
147
- | `highlightInitialWinningCells` | `boolean` | `true` | Show initial highlight before first spin. |
148
- | `queuedSpinStates` | `SpinState[]` | `[]` | Predefined queue consumed by `spin()`. |
149
- | `particleColor` | `'rainbow' \| [number, number, number]` | `[255, 235, 110]` | Win particle color mode or solid RGB color. |
150
-
151
- ## Methods
152
-
153
- ```ts
154
- await reel.init();
155
- reel.spin();
156
- reel.destroy();
157
- ```
158
-
159
- ## Sprite Format
160
-
161
- - Single vertical sprite sheet.
162
- - Every symbol frame is square.
163
- - Total texture height equals `spriteElementsCount * frameWidth` (square-frame assumption).
164
- - `PNG` and `WebP` with transparency are supported.
165
- - When using a cross-origin sprite URL (CDN/sandbox), keep `spriteCrossOrigin: 'anonymous'` and ensure the host returns CORS headers.
166
-
167
- ## License
168
-
169
- MIT
1
+ # cascading-reel
2
+
3
+ A high-performance WebGL cascading reel animator for slot-style UIs on any `HTMLCanvasElement`.
4
+
5
+ - 3x3 reel grid with deterministic scripted outcomes.
6
+ - Queued spins with per-spin callbacks.
7
+ - Win highlight with electric border and particle burst.
8
+ - DPR-aware rendering for mobile and desktop.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install cascading-reel
14
+ ```
15
+
16
+ ## Usage (TypeScript)
17
+
18
+ ```ts
19
+ import { CascadingReel } from 'cascading-reel';
20
+
21
+ const container = document.getElementById('reelWrap');
22
+ const canvas = document.getElementById('canvas');
23
+ const button = document.getElementById('spinBtn');
24
+
25
+ if (!container || !canvas || !button) {
26
+ throw new Error('Demo DOM is not ready');
27
+ }
28
+
29
+ const reel = new CascadingReel({
30
+ container: container as HTMLDivElement,
31
+ canvas: canvas as HTMLCanvasElement,
32
+ button: button as HTMLButtonElement,
33
+ sprite: new URL('./assets/reel.webp', import.meta.url).href,
34
+ spriteCrossOrigin: 'anonymous',
35
+ spriteElementsCount: 6,
36
+ symbolScale: 0.85,
37
+ initialSegments: [
38
+ [0, 1, 2],
39
+ [3, 0, 5],
40
+ [0, 1, 0],
41
+ ],
42
+ queuedSpinStates: [
43
+ {
44
+ stopRows: [
45
+ [0, 4, 5],
46
+ [2, 1, 4],
47
+ [1, 3, 0],
48
+ ],
49
+ finaleSequenceRows: [
50
+ [
51
+ [1, 1, 0],
52
+ [0, 1, 2],
53
+ [4, 5, 1],
54
+ ],
55
+ ],
56
+ highlightWin: true,
57
+ callback: () => console.log('spin complete'),
58
+ },
59
+ ],
60
+ });
61
+
62
+ await reel.init();
63
+ reel.spin();
64
+ ```
65
+
66
+ ## Usage (Vue 3)
67
+
68
+ ```vue
69
+ <script setup lang="ts">
70
+ import { onBeforeUnmount, onMounted, ref, shallowRef } from 'vue';
71
+ import { CascadingReel } from 'cascading-reel';
72
+
73
+ const containerRef = ref<HTMLDivElement | null>(null);
74
+ const canvasRef = ref<HTMLCanvasElement | null>(null);
75
+ const buttonRef = ref<HTMLButtonElement | null>(null);
76
+ const reel = shallowRef<CascadingReel | null>(null);
77
+
78
+ onMounted(async () => {
79
+ if (!containerRef.value || !canvasRef.value) return;
80
+ reel.value = new CascadingReel({
81
+ container: containerRef.value,
82
+ canvas: canvasRef.value,
83
+ button: buttonRef.value ?? undefined,
84
+ sprite: new URL('./assets/reel.webp', import.meta.url).href,
85
+ spriteCrossOrigin: 'anonymous',
86
+ spriteElementsCount: 6,
87
+ symbolScale: 0.85,
88
+ particleColor: 'rainbow',
89
+ });
90
+ await reel.value.init();
91
+ });
92
+
93
+ onBeforeUnmount(() => {
94
+ reel.value?.destroy();
95
+ reel.value = null;
96
+ });
97
+ </script>
98
+
99
+ <template>
100
+ <button ref="buttonRef">Spin</button>
101
+ <div ref="containerRef">
102
+ <canvas ref="canvasRef"></canvas>
103
+ </div>
104
+ </template>
105
+ ```
106
+
107
+ ## HTML Layout
108
+
109
+ ```html
110
+ <button id="spinBtn">Spin</button>
111
+ <div id="reelWrap">
112
+ <canvas id="canvas"></canvas>
113
+ </div>
114
+ ```
115
+
116
+ Call `reel.spin()` to consume the next item from `queuedSpinStates`.
117
+
118
+ ## SpinState
119
+
120
+ ```ts
121
+ type SpinState = {
122
+ stopGrid?: number[][];
123
+ stopRows?: number[][];
124
+ finaleSequence?: number[][][];
125
+ finaleSequenceRows?: number[][][];
126
+ highlightWin?: boolean;
127
+ callback?: () => void;
128
+ };
129
+ ```
130
+
131
+ - Use `stopRows` for row-major input (`[row][col]`).
132
+ - Use `stopGrid` for column-major input (`[col][row]`).
133
+ - `finaleSequenceRows` and `finaleSequence` follow the same row/column conventions.
134
+
135
+ ## Options
136
+
137
+ | Option | Type | Default | Description |
138
+ |:-------------------------------|:-----------------------------------------|:-----------------:|:-------------------------------------------------------|
139
+ | `canvas` | `HTMLCanvasElement` | — | Canvas for rendering. |
140
+ | `container` | `HTMLElement` | — | Element used for responsive sizing. |
141
+ | `button` | `HTMLButtonElement` | — | Optional spin button. |
142
+ | `sprite` | `string \| HTMLImageElement` | — | Sprite sheet URL or preloaded image element. |
143
+ | `spriteCrossOrigin` | `'' \| 'anonymous' \| 'use-credentials'` | `'anonymous'` | `crossOrigin` mode used when `sprite` is a URL string. |
144
+ | `spriteElementsCount` | `number` | `6` | Number of symbols in the sprite sheet. |
145
+ | `symbolScale` | `number` | `0.9` | Symbol scale inside the cell. Clamped to `0.5..1.2`. |
146
+ | `initialSegments` | `number[][]` | randomized | Initial 3x3 state in rows format. |
147
+ | `highlightInitialWinningCells` | `boolean` | `true` | Show initial highlight before first spin. |
148
+ | `queuedSpinStates` | `SpinState[]` | `[]` | Predefined queue consumed by `spin()`. |
149
+ | `particleColor` | `'rainbow' \| [number, number, number]` | `[255, 235, 110]` | Win particle color mode or solid RGB color. |
150
+
151
+ ## Methods
152
+
153
+ ```ts
154
+ await reel.init();
155
+ reel.spin();
156
+ reel.destroy();
157
+ ```
158
+
159
+ ## Sprite Format
160
+
161
+ - Single vertical sprite sheet.
162
+ - Every symbol frame is square.
163
+ - Total texture height equals `spriteElementsCount * frameWidth` (square-frame assumption).
164
+ - `PNG` and `WebP` with transparency are supported.
165
+ - When using a cross-origin sprite URL (CDN/sandbox), keep `spriteCrossOrigin: 'anonymous'` and ensure the host returns CORS headers.
166
+
167
+ ## License
168
+
169
+ MIT