Svelte 5 component · fractalsvelte-ui · Motion
ConfettiBurst
A full-canvas particle celebration effect that emits colorful rotating confetti pieces with ballistic physics and gravity decay.
Install
ConfettiBurst is a Svelte 5 confetti burst component in @fractaldesign/fractalsvelte-ui. It works in SvelteKit and in any Svelte 5 app.
pnpm add @fractaldesign/fractalsvelte-uiImport
import { ConfettiBurst } from '@fractaldesign/fractalsvelte-ui';Usage
<ConfettiBurst particleCount={50} duration={2000} colors={['#10b981', '#6366f1', '#fbbf24', '#f43f5e', '#3b82f6', '#ec4899']} />Props
Also accepts every attribute of HTMLCanvasAttributes, spread onto
the root element.
| Name | Type | Default |
|---|---|---|
particleCount | number | 50 |
duration | number | 2000 |
colors | string[] | ['#10b981', '#6366f1', '#fbbf24', '#f43f5e', '#3b82f6', '#ec4899'] |
class | string | '' |
Source
Show the ConfettiBurst.svelte source
<script lang="ts">
import type { HTMLCanvasAttributes } from 'svelte/elements';
interface Props extends HTMLCanvasAttributes {
particleCount?: number;
duration?: number;
colors?: string[];
class?: string;
}
let {
particleCount = 50,
duration = 2000,
colors = ['#10b981', '#6366f1', '#fbbf24', '#f43f5e', '#3b82f6', '#ec4899'],
class: className = '',
...restProps
}: Props = $props();
let canvasEl: HTMLCanvasElement | undefined = $state();
interface Particle {
x: number;
y: number;
vx: number;
vy: number;
size: number;
color: string;
rotation: number;
vRot: number;
alpha: number;
}
export function burst() {
if (!canvasEl) return;
const canvas = canvasEl;
const ctx = canvas.getContext('2d');
if (!ctx) return;
const rect = canvas.getBoundingClientRect();
const dpr = window.devicePixelRatio || 1;
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
ctx.scale(dpr, dpr);
const originX = rect.width / 2;
const originY = rect.height / 2;
const particles: Particle[] = [];
for (let i = 0; i < particleCount; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = Math.random() * 8 + 3;
particles.push({
x: originX,
y: originY,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed - 3,
size: Math.random() * 6 + 4,
color: colors[Math.floor(Math.random() * colors.length)],
rotation: Math.random() * 360,
vRot: (Math.random() - 0.5) * 15,
alpha: 1
});
}
const startTime = Date.now();
function frame() {
if (!ctx) return;
const elapsed = Date.now() - startTime;
if (elapsed > duration) {
ctx.clearRect(0, 0, rect.width, rect.height);
return;
}
ctx.clearRect(0, 0, rect.width, rect.height);
const progress = elapsed / duration;
for (const p of particles) {
p.x += p.vx;
p.y += p.vy;
p.vy += 0.2; // gravity
p.rotation += p.vRot;
p.alpha = Math.max(0, 1 - progress);
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate((p.rotation * Math.PI) / 180);
ctx.globalAlpha = p.alpha;
ctx.fillStyle = p.color;
ctx.fillRect(-p.size / 2, -p.size / 2, p.size, p.size);
ctx.restore();
}
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
}
</script>
<canvas
bind:this={canvasEl}
class="f-confetti-canvas {className}"
{...restProps}
></canvas>
<style>
@layer fractalsvelte-ui.components {
.f-confetti-canvas {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 100;
}
}
</style>Related components
EqualizerBars A dynamic multi-bar audio frequency visualizer with organic spring-pulsing bars, playing and paused state…FloatingBadge A status badge elevated with gentle sinusoidal vertical float animation and an optional pulsing live…GlowCard A card container wrapped in a cursor-tracking radial spotlight border glow.LidarSweep A circular radar sweep or linear LiDAR plane scanner featuring rotating beam gradients, range rings,…MagneticButton A physics-driven button that smoothly pulls toward cursor coordinates within its interaction perimeter and…MagnetLines A dynamic directional matrix of vector line needles that orient toward pointer coordinates using real-time…