Confetti
The confetti simulation creates customizable particle bursts. Unlike the other simulations, confetti does not auto-spawn — you trigger bursts manually using the burst() method.
Examples
Click to fire
Click anywhere to fire a confetti burst from that position.
<template>
<EffectDemo
ref="containerRef"
clickable
@click="onClick">
<canvas ref="canvasRef"></canvas>
<span class="effect-demo__hint">Click anywhere</span>
</EffectDemo>
</template>
<script
setup
lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { createConfetti } from '@basmilius/sparkle';
const canvasRef = ref<HTMLCanvasElement>();
const containerRef = ref<HTMLDivElement>();
let sim: ReturnType<typeof createConfetti> | null = null;
function onClick(evt: MouseEvent): void {
if (!sim || !containerRef.value) {
return;
}
const rect = containerRef.value.getBoundingClientRect();
sim.burst({
angle: 90,
spread: 60,
particles: 120,
startVelocity: 45,
x: (evt.clientX - rect.left) / rect.width,
y: (evt.clientY - rect.top) / rect.height
});
}
onMounted(() => {
if (canvasRef.value) {
sim = createConfetti();
sim.mount(canvasRef.value).start();
}
});
onUnmounted(() => {
sim?.destroy();
sim = null;
});
</script>Directional bursts
Fire confetti from both sides of the screen simultaneously.
<template>
<EffectDemo>
<canvas ref="canvasRef"></canvas>
<div class="effect-demo__controls">
<button @click="celebrate">Celebrate!</button>
</div>
</EffectDemo>
</template>
<script
setup
lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { createConfetti } from '@basmilius/sparkle';
const canvasRef = ref<HTMLCanvasElement>();
let sim: ReturnType<typeof createConfetti> | null = null;
function celebrate(): void {
if (!sim) {
return;
}
sim.burst({
angle: 45,
spread: 50,
particles: 80,
startVelocity: 50,
x: 0,
y: 0.7
});
sim.burst({
angle: 135,
spread: 50,
particles: 80,
startVelocity: 50,
x: 1,
y: 0.7
});
}
onMounted(() => {
if (canvasRef.value) {
sim = createConfetti();
sim.mount(canvasRef.value).start();
}
});
onUnmounted(() => {
sim?.destroy();
sim = null;
});
</script>Color Palettes
Try different color palettes by clicking the buttons below, then click anywhere to fire.
Color palettes
Select a palette and click anywhere to compare the different color styles.
<template>
<EffectDemo
ref="containerRef"
clickable
@click="onClick">
<canvas ref="canvasRef"></canvas>
<div class="effect-demo__controls">
<button
v-for="(name, key) in paletteNames"
:key="key"
:style="buttonStyle(key)"
@click.stop="onSelect(key, $event)">
{{ name }}
</button>
</div>
</EffectDemo>
</template>
<script
setup
lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import type { Palette } from '@basmilius/sparkle';
import { createConfetti } from '@basmilius/sparkle';
const paletteNames: Record<Palette, string> = {
classic: 'Classic',
pastel: 'Soft Pastels',
vibrant: 'Vibrant Modern',
warm: 'Rich & Warm'
};
const canvasRef = ref<HTMLCanvasElement>();
const containerRef = ref<HTMLDivElement>();
const activePalette = ref<Palette>('vibrant');
let sim: ReturnType<typeof createConfetti> | null = null;
function buttonStyle(palette: Palette): Record<string, string> {
if (palette !== activePalette.value) {
return {};
}
return {
background: 'rgba(255, 255, 255, .2)',
borderColor: 'rgba(255, 255, 255, .3)',
color: 'white'
};
}
function onSelect(palette: Palette, evt: MouseEvent): void {
activePalette.value = palette;
if (!sim || !containerRef.value) {
return;
}
const rect = containerRef.value.getBoundingClientRect();
sim.burst({
angle: 90,
spread: 70,
particles: 120,
startVelocity: 45,
palette,
x: (evt.clientX - rect.left) / rect.width,
y: (evt.clientY - rect.top) / rect.height
});
}
function onClick(evt: MouseEvent): void {
if (!sim || !containerRef.value) {
return;
}
const rect = containerRef.value.getBoundingClientRect();
sim.burst({
angle: 90,
spread: 70,
particles: 120,
startVelocity: 45,
palette: activePalette.value,
x: (evt.clientX - rect.left) / rect.width,
y: (evt.clientY - rect.top) / rect.height
});
}
onMounted(() => {
if (canvasRef.value) {
sim = createConfetti();
sim.mount(canvasRef.value).start();
}
});
onUnmounted(() => {
sim?.destroy();
sim = null;
});
</script>Use a built-in palette:
confetti.burst({
palette: 'warm',
particles: 120
});Or provide custom colors to override the palette:
confetti.burst({
colors: ['#ff0000', '#00ff00', '#0000ff'],
particles: 120
});Available palettes: classic, pastel, vibrant (default), warm.
Custom Shapes
Choose which particle shapes to use:
confetti.burst({
angle: 90,
spread: 60,
particles: 100,
startVelocity: 45,
shapes: ['star', 'circle'],
x: 0.5,
y: 0.5
});Available shapes: bowtie, circle, crescent, diamond, heart, hexagon, ribbon, ring, square, star, triangle.
Physics Tuning
Adjust gravity and decay for different feels:
// Slow, floaty confetti
confetti.burst({
angle: 90,
spread: 90,
particles: 200,
startVelocity: 30,
gravity: 0.5,
decay: 0.95,
ticks: 400,
x: 0.5,
y: 0.5
});// Fast, explosive confetti
confetti.burst({
angle: 90,
spread: 120,
particles: 250,
startVelocity: 70,
gravity: 2,
decay: 0.85,
ticks: 100,
x: 0.5,
y: 0.5
});