Skip to content

Getting Started

Installation

bash
bun add @basmilius/sparkle
bash
npm install @basmilius/sparkle
bash
pnpm add @basmilius/sparkle

Setup

Every effect requires an HTML <canvas> element. The canvas is used as the rendering surface for the effect.

html

<canvas id="canvas"></canvas>
typescript
const canvas = document.getElementById('canvas') as HTMLCanvasElement;

Quick Start

Fireworks

An automatic firework display with 16 explosion variants:

typescript
import { createFireworks } from '@basmilius/sparkle';

const fireworks = createFireworks();
fireworks.mount(canvas).start();

Confetti

Fire confetti bursts on demand:

typescript
import { createConfetti } from '@basmilius/sparkle';

const confetti = createConfetti();
confetti.mount(canvas);

confetti.burst({
    angle: 90,
    spread: 60,
    particles: 150,
    startVelocity: 45,
    x: 0.5,
    y: 0.5
});

Snow

A continuous snowfall effect:

typescript
import { createSnow } from '@basmilius/sparkle';

const snow = createSnow();
snow.mount(canvas).start();

Lifecycle

All simulations share the same lifecycle methods:

typescript
// Mount to a canvas element and start the animation loop.
sim.mount(canvas).start();

// Temporarily pause the animation loop.
sim.pause();

// Resume after pausing.
sim.start();

// Stop and remove all event listeners.
sim.destroy();

Simulations automatically pause when the browser tab is hidden and resume when it becomes visible again.

Runtime Control

Effects can be updated while they are running. Use configure() to change any config option on the fly — only the keys you pass are updated — and pause() / resume() to halt and continue the render loop without losing state.

Runtime control

Pause and resume the snowfall, and adjust its speed live with configure().

<template>
    <EffectDemo>
        <canvas ref="canvasRef"></canvas>

        <div class="effect-demo__controls">
            <button @click="toggle">{{ paused ? 'Resume' : 'Pause' }}</button>
            <button
                :style="buttonStyle(0.5)"
                @click="setSpeed(0.5)">
                Gentle
            </button>
            <button
                :style="buttonStyle(1)"
                @click="setSpeed(1)">
                Normal
            </button>
            <button
                :style="buttonStyle(2.5)"
                @click="setSpeed(2.5)">
                Blizzard
            </button>
        </div>
    </EffectDemo>
</template>

<script
    setup
    lang="ts">
    import { onMounted, onUnmounted, ref } from 'vue';
    import { createSnow } from '@basmilius/sparkle';

    const canvasRef = ref<HTMLCanvasElement>();
    const paused = ref(false);
    const speed = ref(1);
    let sim: ReturnType<typeof createSnow> | null = null;

    function buttonStyle(value: number): Record<string, string> {
        if (value !== speed.value) {
            return {};
        }

        return {
            background: 'rgba(255, 255, 255, .2)',
            borderColor: 'rgba(255, 255, 255, .3)',
            color: 'white'
        };
    }

    function toggle(): void {
        if (!sim) {
            return;
        }

        if (paused.value) {
            sim.resume();
        } else {
            sim.pause();
        }

        paused.value = !paused.value;
    }

    function setSpeed(value: number): void {
        speed.value = value;
        sim?.configure({speed: value});
    }

    onMounted(() => {
        if (canvasRef.value) {
            sim = createSnow();
            sim.mount(canvasRef.value).start();
        }
    });

    onUnmounted(() => {
        sim?.destroy();
        sim = null;
    });
</script>
typescript
// Change options on the fly — only the passed keys are updated.
snow.configure({ speed: 2.5 });

// Pause and resume the render loop.
snow.pause();
snow.resume();