Skip to content

Repository files navigation

solitaire-victory.js

The Solitaire victory animation as a drop-in canvas plugin. The classic trail-smearing bounce plus scatter, rain, fountain, and cyclone effects — 52 procedurally-drawn cards, zero dependencies, no build step.

Live demo →

Anyone who ever won a game of Solitaire on Windows remembers the payoff: cards launching off their foundations, bouncing across the felt, smearing trails behind them because the screen never repainted. solitaire-victory.js recreates that — faithfully — and then keeps going with four more ways to shower a screen in playing cards.

Install

npm install @goboldlyforward/solitaire-victory

Or grab the files directly:

<link rel="stylesheet" href="path/to/solitaire-victory.css">
<script src="path/to/solitaire-victory.js"></script>

Works as a plain global (SolitaireVictory) or a CommonJS module.

Quick start

<div id="stage" style="height: 60vh"></div>

<script>
  const win = new SolitaireVictory('#stage');

  win.play('bounce').then(() => {
    console.log('all 52 cards are down');
  });
</script>

Or skip the container entirely — the one-liner throws a fullscreen overlay over your whole app, plays once, fades out, and removes itself. Clicks pass straight through the entire time:

SolitaireVictory.celebrate();                                 // classic bounce
SolitaireVictory.celebrate({ effect: 'scatter', holdMs: 500 }); // any effect + options

Effects

Effect What happens
bounce The 1990 classic. Cards launch one-by-one from foundation piles, bounce off the floor, and smear trails because the canvas never repaints.
scatter The whole deck blasts outward from the center and tumbles off-screen.
rain Cards fall from the sky, tumbling, a mix of faces and backs. With loop: true they recycle seamlessly forever.
fountain A geyser of cards from the bottom center — confetti-cannon energy.
cyclone Cards spiral out from the center in a widening vortex.

Every card face — pips, courts, and the patterned back — is drawn programmatically on canvas and cached as a sprite, so cards stay crisp at any size and any devicePixelRatio.

Options

new SolitaireVictory('#stage', {
  effect:        'bounce',   // 'bounce' | 'scatter' | 'rain' | 'fountain' | 'cyclone'
  cards:         52,         // deck size the effect animates
  cardWidth:     72,         // px; height keeps the 2.5 × 3.5 poker ratio
  speed:         1,          // global time multiplier
  gravity:       2200,       // px/s²
  restitution:   0.82,       // bounce: energy kept per floor hit
  stagger:       0.4,        // bounce: seconds between card launches
  piles:         4,          // bounce: foundation piles across the top
  loop:          false,      // replay forever (rain recycles seamlessly)
  trails:        null,       // null = effect default (bounce smears, others don't)
  background:    null,       // canvas backdrop; null = transparent
  backColor:     '#2b4d9b',  // card-back color
  faceDownRatio: null,       // fraction of face-down cards (rain 0.35, cyclone 0.25)
  onComplete:    null,       // fn({ effect, willLoop }) — fires every completion
  autoplay:      false,      // play() immediately on construct
});

With background: null (the default) the canvas is transparent, so your own CSS — a green felt gradient, an image, anything — shows through, and bounce trails smear right over it.

Methods

win.play(effect?, overrides?);  // returns a Promise: 'complete' | 'stopped'
win.pause();
win.resume();
win.stop();                     // halt + wipe the canvas (trails included)
win.clear();                    // wipe trails without ending the run
win.setOptions({ ... });        // merge + apply; speed/gravity change live
win.resize();                   // manual re-measure (auto via ResizeObserver)
win.destroy();                  // tear down canvas + listeners
win.isPlaying;                  // boolean
SolitaireVictory.EFFECTS;                 // ['bounce', 'scatter', 'rain', 'fountain', 'cyclone']

play() interrupts any run already in progress. setOptions() applies speed, gravity, restitution, and stagger live mid-run; changing effect, cards, cardWidth, or the deck's look restarts the current run.

Trails, the signature move

The bounce effect never clears the canvas — that's the whole trick, exactly like the original. trails is overridable per effect:

win.play('rain', { trails: true });    // rain that smears — surprisingly great
win.play('bounce', { trails: false }); // a tidy, repainting bounce

Mounting

  • An element (new SolitaireVictory('#stage')) — a canvas is injected and fills it; anything else inside the host auto-stacks above the cards.
  • A <canvas> — painted directly, no wrapper.
  • Nothing / document.body (new SolitaireVictory()) — a fixed, fullscreen, click-through overlay is created for you (that's what SolitaireVictory.celebrate() uses).

License

MIT © Go Boldly Forward

About

The Solitaire victory animation as a drop-in canvas plugin — bounce, scatter, rain, fountain, cyclone

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages