Skip to content

Fireworks

The fireworks simulation creates a continuous display with 16 unique explosion variants, 3D depth effects, and configurable scale. Fireworks are launched automatically and explode into one of the available variants.

Examples

Basic

An auto-spawning firework display with default settings.

<template>
    <div class="effect-demo">
        <canvas ref="canvasRef"></canvas>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';

const canvasRef = ref<HTMLCanvasElement>();
let sim: { destroy(): void } | null = null;

onMounted(async () => {
    const { FireworkSimulation } = await import('@basmilius/sparkle');

    if (canvasRef.value) {
        sim = new FireworkSimulation(canvasRef.value, {scale: 0.5});
        sim.start();
    }
});

onUnmounted(() => {
    sim?.destroy();
    sim = null;
});
</script>

Manual control

Click anywhere on the canvas to fire a random explosion at that position.

Click anywhere to fire a random explosion

<template>
    <div ref="containerRef" class="effect-demo effect-demo--clickable">
        <canvas ref="canvasRef"></canvas>

        <span class="effect-demo__hint">Click anywhere to fire a random explosion</span>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';

const canvasRef = ref<HTMLCanvasElement>();
const containerRef = ref<HTMLDivElement>();
let sim: { fireExplosion(variant: string, position: { x: number; y: number }): void; destroy(): void } | null = null;
let variants: string[] = [];

function onClick(evt: MouseEvent): void {
    if (!sim || !containerRef.value || variants.length === 0) {
        return;
    }

    const rect = containerRef.value.getBoundingClientRect();
    const variant = variants[Math.floor(Math.random() * variants.length)];

    sim.fireExplosion(variant, {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    });
}

onMounted(async () => {
    const { FIREWORK_VARIANTS, FireworkSimulation } = await import('@basmilius/sparkle');

    variants = [...FIREWORK_VARIANTS];

    if (canvasRef.value && containerRef.value) {
        sim = new FireworkSimulation(canvasRef.value, {scale: 0.5, autoSpawn: false});
        sim.start();
        containerRef.value.addEventListener('click', onClick);
    }
});

onUnmounted(() => {
    containerRef.value?.removeEventListener('click', onClick);
    sim?.destroy();
    sim = null;
});
</script>

Variant picker

Try each of the 16 variants individually using the buttons.

<template>
    <div ref="containerRef" class="effect-demo">
        <canvas ref="canvasRef"></canvas>

        <div v-if="ready" class="effect-demo__controls">
            <button v-for="variant in variants"
                    :key="variant"
                    @click="fire(variant)">
                {{ variant }}
            </button>
        </div>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';

const canvasRef = ref<HTMLCanvasElement>();
const containerRef = ref<HTMLDivElement>();
const ready = ref(false);
const variants = ref<string[]>([]);
let sim: { fireExplosion(variant: string, position: { x: number; y: number }): void; destroy(): void } | null = null;

function fire(variant: string): void {
    if (!sim || !containerRef.value) {
        return;
    }

    const rect = containerRef.value.getBoundingClientRect();

    sim.fireExplosion(variant, {
        x: rect.width * (0.2 + Math.random() * 0.6),
        y: rect.height * (0.15 + Math.random() * 0.35)
    });
}

onMounted(async () => {
    const { FIREWORK_VARIANTS, FireworkSimulation } = await import('@basmilius/sparkle');

    variants.value = [...FIREWORK_VARIANTS];

    if (canvasRef.value) {
        sim = new FireworkSimulation(canvasRef.value, {scale: 0.5, autoSpawn: false});
        sim.start();
        ready.value = true;
    }
});

onUnmounted(() => {
    sim?.destroy();
    sim = null;
});
</script>

Scaling

Use the scale option to control the overall size of all effects:

typescript
// Smaller, more subtle fireworks
const sim = new FireworkSimulation(canvas, { scale: 0.5 });

// Bigger, more dramatic fireworks
const sim = new FireworkSimulation(canvas, { scale: 2 });

Variants

There are 16 variants organized in four categories.

Classic

VariantDescription
peonyClassic spherical burst with round particles.
chrysanthemumDense burst with long trailing particles and sparkle.
willowParticles fall gracefully with very long trails, like a weeping willow.
palmNarrow upward cone that arcs into drooping trails.
brocadeDense golden shimmer trails in warm amber tones.
horsetailNarrow upward fountain with extreme gravity, creating a cascade.

Geometric

VariantDescription
ringParticles form a perfect circle with diamond shapes.
concentricTwo concentric rings at different sizes with complementary colors.
saturnA filled 3D sphere with a tilted elliptical ring around it.

Shapes

VariantDescription
heartParticles follow a parametric heart curve.
flowerRose curve that creates a petal pattern with 4-8 lobes.
spiralMultiple arms that spiral outward like a galaxy.
dahliaMulti-colored petal clusters with alternating hues.

Effects

VariantDescription
crackleStar-shaped particles that create spark flashes when dying.
crossetteParticles that split into 4 sub-explosions mid-flight.
strobeParticles that blink on/off at ~10Hz.