Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

long-confetti

longleon182MIT1.0.1TypeScript support: included

A JavaScript library for creating beautiful confetti animations using custom PNG/SVG images instead of traditional shapes. Features realistic physics, customizable effects, and built-in presets.

confetti, animation, javascript, images, particles, celebration, effects, physics, dom, browser, svg, png, custom-images, long-confetti, party, visual-effects, cdn, unpkg, jsdelivr

readme

🎉 Long Confetti

A JavaScript library for creating beautiful confetti animations using custom PNG/SVG images instead of traditional shapes. Perfect for celebrations, achievements, games, and any visual enhancement that needs floating custom images!

✨ Features

  • 🖼️ Custom Images: Use up to 5 different PNG/SVG images as confetti particles
  • Physics Engine: Realistic gravity, wind, and velocity simulation
  • 🎯 Flexible Origins: Launch confetti from any position on screen
  • 📐 Customizable: Adjust size, rotation, duration, and particle count
  • 🎭 Built-in Defaults: Emoji and geometric shape presets included
  • 🚀 Performance: Optimized DOM manipulation and RAF animation
  • 📱 Responsive: Works on all screen sizes and devices
  • 🔧 TypeScript: Full TypeScript support with type definitions
  • 🌐 Browser Ready: Works directly in browsers without build tools

🚀 Installation & Setup

Method 1: CDN Import (Easiest - No Node.js Required!)

Simply include the CDN script in your HTML - no build tools or Node.js needed:

<!-- From jsDelivr CDN -->
<script src="https://cdn.jsdelivr.net/npm/long-confetti@1.0.0/long-confetti.cdn.js"></script>

<!-- Or from unpkg CDN -->
<script src="https://unpkg.com/long-confetti@1.0.0/long-confetti.cdn.js"></script>

Then use it immediately:

<script>
  // Functions are globally available!
  fireShapeConfetti({ particleCount: 100 });
  fireEmojiConfetti({ duration: 4000 });
</script>

Method 2: NPM/Yarn (For Projects with Build Tools)

npm install long-confetti

Or with yarn:

yarn add long-confetti

Method 3: Direct File Usage (Local Development)

Download and include the files directly:

<!-- Use the CDN-ready version -->
<script src="long-confetti.cdn.js"></script>

<!-- Or use the source file -->
<script src="src/index.js"></script>

📖 Complete CDN Example (Super Easy!)

Here's a minimal example using the CDN - just save as .html and open in any browser:

<!DOCTYPE html>
<html>
<head>
    <title>Long Confetti - CDN Example</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            text-align: center;
            padding: 50px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            min-height: 100vh;
            margin: 0;
        }
        button {
            padding: 15px 30px;
            font-size: 18px;
            margin: 10px;
            border: none;
            border-radius: 8px;
            background: rgba(255,255,255,0.2);
            color: white;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        button:hover {
            background: rgba(255,255,255,0.3);
            transform: translateY(-2px);
        }
    </style>
</head>
<body>
    <h1>🎉 Long Confetti CDN Demo</h1>
    <p>No Node.js, no build tools, no installation - just works!</p>

    <button onclick="fireShapeConfetti({particleCount: 100})">
        🔷 Shape Confetti
    </button>

    <button onclick="fireEmojiConfetti({particleCount: 75, duration: 4000})">
        😊 Emoji Confetti
    </button>

    <button onclick="customConfetti()">
        ⭐ Custom Images
    </button>

    <button onclick="stopAllConfetti()">
        ⏹️ Stop All
    </button>

    <!-- Include Long Confetti from CDN -->
    <script src="https://cdn.jsdelivr.net/npm/long-confetti@1.0.0/long-confetti.cdn.js"></script>

    <script>
        function customConfetti() {
            const hearts = [
                'data:image/svg+xml;base64,' + btoa(`
                    <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
                        <path d="M16 28 C16 28 2 18 2 10 C2 6 6 2 10 2 C12 2 16 6 16 6 C16 6 20 2 22 2 C26 2 30 6 30 10 C30 18 16 28 16 28 Z" 
                              fill="#FF6B9D"/>
                    </svg>
                `)
            ];

            fireConfetti(hearts, {
                particleCount: 50,
                duration: 3000,
                spread: 70
            });
        }
    </script>
</body>
</html>

📖 Complete Advanced Example (From Scratch)

For more advanced usage with a full test suite:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Confetti Demo</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            margin: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            color: white;
        }

        .demo-container {
            text-align: center;
            padding: 40px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            backdrop-filter: blur(10px);
            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
        }

        h1 {
            margin-bottom: 30px;
            font-size: 2.5em;
        }

        .button-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 15px;
            margin-top: 30px;
        }

        button {
            padding: 15px 25px;
            font-size: 16px;
            border: none;
            border-radius: 10px;
            background: rgba(255, 255, 255, 0.2);
            color: white;
            cursor: pointer;
            transition: all 0.3s ease;
            backdrop-filter: blur(5px);
        }

        button:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
        }

        button:active {
            transform: translateY(0);
        }

        .instructions {
            margin-top: 30px;
            padding: 20px;
            background: rgba(0, 0, 0, 0.2);
            border-radius: 10px;
            font-size: 14px;
            line-height: 1.6;
        }
    </style>
</head>
<body>
    <div class="demo-container">
        <h1>🎉 Image Confetti Demo</h1>
        <p>Click any button below to see different confetti effects!</p>

        <div class="button-grid">
            <button id="shapeBtn">🔷 Geometric Shapes</button>
            <button id="emojiBtn">😊 Emoji Confetti</button>
            <button id="customBtn">⭐ Custom Images</button>
            <button id="celebrationBtn">🎊 Celebration</button>
            <button id="burstBtn">💥 Center Burst</button>
            <button id="multiBtn">🎪 Multiple Effects</button>
        </div>

        <div class="instructions">
            <strong>How this works:</strong><br>
            1. Save this HTML file to your computer<br>
            2. Make sure the long-confetti source file is in the correct path<br>
            3. Open the HTML file in any modern browser<br>
            4. Click buttons to see confetti effects!
        </div>
    </div>

    <!-- Include the Image Confetti library -->
    <!-- Option 1: From src folder (if you have the source) -->
    <script src="src/index.js"></script>

    <!-- Option 2: From dist folder (if you built the project) -->
    <!-- <script src="dist/index.js"></script> -->

    <!-- Option 3: If you downloaded just this HTML file, you'll need to adjust the path -->
    <!-- <script src="path/to/your/long-confetti/src/index.js"></script> -->

    <script>
        // Wait for the library to load
        document.addEventListener('DOMContentLoaded', function() {
            // Check if library loaded successfully
            if (typeof window.fireShapeConfetti === 'undefined') {
                alert('Image Confetti library not found! Please check the script src path.');
                return;
            }

            // 1. Default geometric shapes
            document.getElementById('shapeBtn').addEventListener('click', async function() {
                await window.fireShapeConfetti({
                    particleCount: 100,
                    duration: 4000,
                    origin: { x: 0.5, y: 0.1 }
                });
            });

            // 2. Default emojis (🎉⭐❤️🌟🎈)
            document.getElementById('emojiBtn').addEventListener('click', async function() {
                await window.fireEmojiConfetti({
                    particleCount: 75,
                    duration: 3000,
                    origin: { x: 0.5, y: 0.1 }
                });
            });

            // 3. Custom SVG images
            document.getElementById('customBtn').addEventListener('click', async function() {
                const customImages = [
                    // Star SVG
                    'data:image/svg+xml;base64,' + btoa(`
                        <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
                            <path d="M16 2 L20 12 L30 12 L22 18 L26 28 L16 22 L6 28 L10 18 L2 12 L12 12 Z" 
                                  fill="#FFD700" stroke="#FFA500" stroke-width="1"/>
                        </svg>
                    `),
                    // Heart SVG
                    'data:image/svg+xml;base64,' + btoa(`
                        <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
                            <path d="M16 28 C16 28 2 18 2 10 C2 6 6 2 10 2 C12 2 16 6 16 6 C16 6 20 2 22 2 C26 2 30 6 30 10 C30 18 16 28 16 28 Z" 
                                  fill="#FF6B9D"/>
                        </svg>
                    `),
                    // Diamond SVG
                    'data:image/svg+xml;base64,' + btoa(`
                        <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
                            <path d="M16 2 L26 12 L16 30 L6 12 Z" 
                                  fill="#4ECDC4" stroke="#45B7D1" stroke-width="1"/>
                        </svg>
                    `)
                ];

                await window.fireConfetti(customImages, {
                    particleCount: 60,
                    duration: 4000,
                    startVelocity: 35,
                    spread: 70,
                    origin: { x: 0.5, y: 0.1 },
                    imageSize: { width: 25, height: 25 },
                    rotationSpeed: 6
                });
            });

            // 4. Celebration effect (top-down)
            document.getElementById('celebrationBtn').addEventListener('click', async function() {
                await window.fireShapeConfetti({
                    particleCount: 150,
                    duration: 5000,
                    startVelocity: 40,
                    spread: 90,
                    origin: { x: 0.5, y: 0.1 },
                    gravity: 0.6
                });
            });

            // 5. Center burst
            document.getElementById('burstBtn').addEventListener('click', async function() {
                await window.fireEmojiConfetti({
                    particleCount: 100,
                    duration: 3000,
                    startVelocity: 50,
                    spread: 360,
                    origin: { x: 0.5, y: 0.5 }
                });
            });

            // 6. Multiple sequential effects
            document.getElementById('multiBtn').addEventListener('click', async function() {
                // Left cannon
                setTimeout(async () => {
                    await window.fireEmojiConfetti({
                        particleCount: 50,
                        origin: { x: 0.1, y: 0.7 },
                        spread: 45,
                        startVelocity: 40
                    });
                }, 0);

                // Right cannon
                setTimeout(async () => {
                    await window.fireEmojiConfetti({
                        particleCount: 50,
                        origin: { x: 0.9, y: 0.7 },
                        spread: 45,
                        startVelocity: 40
                    });
                }, 200);

                // Center finale
                setTimeout(async () => {
                    await window.fireShapeConfetti({
                        particleCount: 100,
                        origin: { x: 0.5, y: 0.5 },
                        spread: 360,
                        startVelocity: 55
                    });
                }, 400);
            });

            console.log('Image Confetti Demo Ready! 🎉');
        });
    </script>
</body>
</html>

📖 Quick Start Guide

Step 1: Get the Files

  1. Download or clone this repository
  2. The main file you need is src/index.js

Step 2: Basic HTML Setup

<!DOCTYPE html>
<html>
<head>
    <title>My Confetti App</title>
</head>
<body>
    <button id="confetti-btn">🎉 Fire Confetti!</button>

    <!-- Include the library -->
    <script src="src/index.js"></script>

    <script>
        document.getElementById('confetti-btn').addEventListener('click', async () => {
            // Fire some confetti!
            await window.fireShapeConfetti({
                particleCount: 100,
                duration: 3000
            });
        });
    </script>
</body>
</html>

🎯 Usage Examples

1. Basic Confetti Effects

// Default geometric shapes (circles, squares, triangles, stars)
await window.fireShapeConfetti({
    particleCount: 100,
    duration: 4000,
    origin: { x: 0.5, y: 0.1 }
});

// Default emojis (🎉⭐❤️🌟🎈)
await window.fireEmojiConfetti({
    particleCount: 75,
    duration: 3000,
    origin: { x: 0.5, y: 0.5 }
});

// Custom images
const customImages = [
    'path/to/your/image1.png',
    'path/to/your/image2.svg',
    'data:image/svg+xml;base64,' + btoa('<svg>...</svg>')
];

await window.fireConfetti(customImages, {
    particleCount: 50,
    duration: 3000,
    startVelocity: 30,
    spread: 70,
    origin: { x: 0.5, y: 0.1 },
    gravity: 0.5,
    wind: 0.1,
    imageSize: { width: 20, height: 20 },
    rotationSpeed: 5,
    zIndex: 9999
});

2. Node.js/Module Usage (If using NPM)

import { fireShapeConfetti, fireEmojiConfetti, fireConfetti } from "long-confetti";

// Default shapes - colorful geometric shapes
await fireShapeConfetti({
  particleCount: 100,
  duration: 5000,
  origin: { x: 0.5, y: 0.1 }
});

// Default emojis - fun emoji confetti (🎉⭐❤️🌟🎈)
await fireEmojiConfetti({
  particleCount: 150,
  duration: 4000,
  origin: { x: 0.5, y: 0.5 }
});

// Custom images - your own PNG/SVG images
await fireConfetti(
  ["/images/star.png", "/images/heart.png", "/images/diamond.png"],
  {
    particleCount: 50,
    duration: 3000,
    startVelocity: 30,
    spread: 70,
    gravity: 0.5,
    wind: 0.1,
    imageSize: { width: 25, height: 25 },
    rotationSpeed: 5
  }
);

3. React Integration

import React, { useRef, useEffect } from "react";

// For NPM/module usage (if working)
// import { fireEmojiConfetti, fireConfetti, fireShapeConfetti } from "long-confetti";

function CelebrationComponent() {
  const confettiLoaded = useRef(false);

  useEffect(() => {
    // Load the fixed library script if not already loaded
    if (!confettiLoaded.current && !window.fireConfetti) {
      const script = document.createElement('script');
      script.src = '/image-confetti-fixed.js'; // Adjust path as needed
      script.onload = () => {
        confettiLoaded.current = true;
        console.log('Image Confetti library loaded');
      };
      document.head.appendChild(script);
    }
  }, []);

  // Simple emoji celebration
  const handleEmojiClick = async () => {
    if (window.fireEmojiConfetti) {
      await window.fireEmojiConfetti({ 
        particleCount: 100,
        duration: 4000,
        origin: { x: 0.5, y: 0.1 }
      });
    }
  };

  // Custom images
  const handleCustomClick = async () => {
    if (window.fireConfetti) {
      // Create custom SVG logos as data URLs
      const customLogos = [
        'data:image/svg+xml;base64,' + btoa(`
          <svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
            <circle cx="32" cy="32" r="30" fill="#ff6b6b"/>
            <text x="32" y="40" text-anchor="middle" fill="white" font-size="24" font-family="Arial">★</text>
          </svg>
        `),
        'data:image/svg+xml;base64,' + btoa(`
          <svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
            <rect x="8" y="8" width="48" height="48" fill="#4ecdc4"/>
            <text x="32" y="40" text-anchor="middle" fill="white" font-size="24" font-family="Arial">♥</text>
          </svg>
        `)
      ];

      await window.fireConfetti(customLogos, {
        particleCount: 75,
        duration: 4000,
        startVelocity: 35,
        spread: 60,
        origin: { x: 0.5, y: 0.1 },
        gravity: 0.5,
        wind: 0.1,
        imageSize: { width: 25, height: 25 },
        rotationSpeed: 6
      });
    }
  };

  // Geometric shapes
  const handleShapesClick = async () => {
    if (window.fireShapeConfetti) {
      await window.fireShapeConfetti({
        particleCount: 150,
        duration: 5000,
        startVelocity: 40,
        spread: 90,
        origin: { x: 0.5, y: 0.5 }
      });
    }
  };

  // Multiple effects sequence
  const handleMultipleEffects = async () => {
    if (window.fireConfetti && window.fireEmojiConfetti) {
      // Fire from left
      setTimeout(() => {
        window.fireEmojiConfetti({
          particleCount: 50,
          origin: { x: 0.1, y: 0.7 },
          spread: 45
        });
      }, 0);

      // Fire from right
      setTimeout(() => {
        window.fireEmojiConfetti({
          particleCount: 50,
          origin: { x: 0.9, y: 0.7 },
          spread: 45
        });
      }, 200);

      // Center burst
      setTimeout(() => {
        window.fireShapeConfetti({
          particleCount: 100,
          origin: { x: 0.5, y: 0.5 },
          spread: 360
        });
      }, 400);
    }
  };

  return (
    <div style={{ padding: '20px', textAlign: 'center' }}>
      <h2>🎉 React Confetti Demo</h2>
      <div style={{ display: 'flex', gap: '10px', justifyContent: 'center', flexWrap: 'wrap' }}>
        <button onClick={handleEmojiClick} style={{ padding: '10px 20px', fontSize: '16px' }}>
          🎉 Emoji Confetti
        </button>
        <button onClick={handleCustomClick} style={{ padding: '10px 20px', fontSize: '16px' }}>
          ⭐ Custom Images
        </button>
        <button onClick={handleShapesClick} style={{ padding: '10px 20px', fontSize: '16px' }}>
          🔷 Geometric Shapes
        </button>
        <button onClick={handleMultipleEffects} style={{ padding: '10px 20px', fontSize: '16px' }}>
          🎊 Multiple Effects
        </button>
      </div>
    </div>
  );
}

export default CelebrationComponent;

4. Advanced Class Usage

// Create a persistent confetti instance
const confetti = new window.ImageConfetti();

// Fire multiple effects
await confetti.fire({
  images: ['/logo1.png', '/logo2.png'],
  particleCount: 50,
  duration: 3000
});

// Clean up when done
setTimeout(() => {
  confetti.destroy(); // Removes from DOM completely
}, 5000);

🎛️ Configuration Options

interface ImageConfettiOptions {
  images?: string[]; // Array of image URLs (up to 5) - optional, uses defaults if not provided
  particleCount?: number; // Number of particles (default: 50)
  duration?: number; // Animation duration in ms (default: 3000)
  gravity?: number; // Gravity strength (default: 0.5)
  wind?: number; // Wind force (default: 0.1)
  startVelocity?: number; // Initial velocity (default: 30)
  spread?: number; // Launch angle spread in degrees (default: 50)
  origin?: {
    // Launch position (default: { x: 0.5, y: 0.1 })
    x: number; // 0-1, left to right (0 = left edge, 1 = right edge)
    y: number; // 0-1, top to bottom (0 = top edge, 1 = bottom edge)
  };
  zIndex?: number; // CSS z-index (default: 9999)
  imageSize?: {
    // Particle size (default: { width: 20, height: 20 })
    width: number;
    height: number;
  };
  rotationSpeed?: number; // Rotation speed (default: 5)
}

Available Functions

// Custom images
window.fireConfetti(imageUrls, options)

// Default emojis (🎉⭐❤️🌟🎈)
window.fireEmojiConfetti(options)

// Default geometric shapes (circles, squares, triangles, stars)
window.fireShapeConfetti(options)

// Advanced class usage
const confetti = new window.ImageConfetti();
await confetti.fire(options);
confetti.stop();     // Stop animation but keep container
confetti.destroy();  // Remove from DOM completely

🎨 Common Effect Patterns

Celebration Effects

// 🎉 Top celebration - particles fall from top
await window.fireShapeConfetti({
  particleCount: 100,
  duration: 4000,
  startVelocity: 35,
  spread: 60,
  origin: { x: 0.5, y: 0.1 }, // Top center
  gravity: 0.6
});

// 💥 Center burst - particles explode outward
await window.fireEmojiConfetti({
  particleCount: 75,
  duration: 2500,
  startVelocity: 45,
  spread: 90,
  origin: { x: 0.5, y: 0.5 }, // Center
  gravity: 0.5
});

// ⛲ Fountain effect - particles shoot up from bottom
await window.fireShapeConfetti({
  particleCount: 30,
  duration: 5000,
  startVelocity: 25,
  spread: 30,
  origin: { x: 0.5, y: 0.9 }, // Bottom center
  gravity: 0.3 // Light gravity for floating effect
});

Side Cannon Effects

// 🎪 Left side cannon
await window.fireEmojiConfetti({
  particleCount: 60,
  duration: 3500,
  startVelocity: 40,
  spread: 45,
  origin: { x: 0.1, y: 0.7 }, // Left side
  wind: 0.2 // Push particles right
});

// 🎪 Right side cannon
await window.fireEmojiConfetti({
  particleCount: 60,
  duration: 3500,
  startVelocity: 40,
  spread: 45,
  origin: { x: 0.9, y: 0.7 }, // Right side
  wind: -0.2 // Push particles left
});

🎯 Advanced Usage

Multiple Sequential Effects

// Fire multiple effects in sequence for maximum celebration
const sequentialCelebration = async () => {
  // Left cannon
  setTimeout(async () => {
    await window.fireEmojiConfetti({
      particleCount: 50,
      origin: { x: 0.1, y: 0.7 },
      spread: 45
    });
  }, 0);

  // Right cannon
  setTimeout(async () => {
    await window.fireEmojiConfetti({
      particleCount: 50,
      origin: { x: 0.9, y: 0.7 },
      spread: 45
    });
  }, 200);

  // Center burst finale
  setTimeout(async () => {
    await window.fireShapeConfetti({
      particleCount: 100,
      origin: { x: 0.5, y: 0.5 },
      spread: 360,
      startVelocity: 50
    });
  }, 400);
};

sequentialCelebration();

Custom Physics and Styling

// ❄️ Winter scene with custom physics
const snowflakeImage = 'data:image/svg+xml;base64,' + btoa(`
  <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
    <path d="M16 2 L16 30 M2 16 L30 16 M6 6 L26 26 M6 26 L26 6" 
          stroke="#87CEEB" stroke-width="2" stroke-linecap="round"/>
  </svg>
`);

await window.fireConfetti([snowflakeImage], {
  particleCount: 100,
  duration: 10000,
  gravity: 0.1, // Very light gravity for floating effect
  wind: -0.3, // Strong left wind
  startVelocity: 15, // Gentle start
  spread: 180, // Full semicircle spread
  origin: { x: 0.5, y: 0 }, // Top of screen
  imageSize: { width: 15, height: 15 },
  rotationSpeed: 2, // Slow gentle rotation
});

// 🌟 Golden celebration with custom images
const starImage = 'data:image/svg+xml;base64,' + btoa(`
  <svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
    <path d="M16 2 L20 12 L30 12 L22 18 L26 28 L16 22 L6 28 L10 18 L2 12 L12 12 Z" 
          fill="#FFD700" stroke="#FFA500" stroke-width="1"/>
  </svg>
`);

await window.fireConfetti([starImage], {
  particleCount: 200,
  duration: 6000,
  gravity: 0.8,
  wind: 0.2,
  startVelocity: 50,
  spread: 120,
  origin: { x: 0.2, y: 0.3 },
  imageSize: { width: 30, height: 30 },
  rotationSpeed: 8,
  zIndex: 10000,
});

Persistent Confetti Instance

// Create a single confetti instance for multiple effects
const confetti = new window.ImageConfetti();

// Method 1: Use defaults (colorful geometric shapes)
await confetti.fire();

// Method 2: Custom images with full control
await confetti.fire({
  images: ["/logo1.png", "/logo2.png"],
  particleCount: 200,
  duration: 6000,
  gravity: 0.8,
  wind: 0.2,
  startVelocity: 50,
  spread: 120,
  origin: { x: 0.2, y: 0.3 },
  imageSize: { width: 30, height: 30 },
  rotationSpeed: 8,
  zIndex: 10000,
});

// Stop current animation but keep the container for reuse
confetti.stop();

// Remove confetti container from DOM completely when done
confetti.destroy();

🌐 Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+
  • Mobile browsers (iOS Safari, Chrome Mobile)

🔧 Development

Building from Source

# Clone the repository
git clone https://github.com/longleon/long-confetti.git
cd long-confetti

# Install dependencies
npm install

# Build TypeScript
npm run build

# Run tests
npm test

# Start development server
npm run dev

Project Structure

long-confetti/
├── src/
│   └── index.js          # Main library source code
├── dist/                 # Built distribution files
│   ├── index.js         # CommonJS build
│   ├── index.d.ts       # TypeScript definitions
│   └── *.map            # Source maps
├── package.json         # Package configuration
├── README.md           # Documentation (this file)
├── LICENSE             # MIT License
└── node_modules/       # Dependencies

📝 Image Requirements

  • Format: PNG, JPG, GIF, WebP, or SVG
  • Size: Recommended 64x64px or smaller for best performance
  • CORS: Images from external domains need proper CORS headers
  • Transparency: PNG with transparency works best for realistic confetti effect

🚨 Common Issues & Solutions

Library Not Loading

Problem: window.fireConfetti is not a function

// Solution: Check if library is loaded before using
if (typeof window.fireConfetti === 'function') {
  await window.fireConfetti(images, options);
} else {
  console.error('Image Confetti library not loaded');
}

Images Not Loading

Problem: Custom images not displaying as confetti

// Solution 1: Use data URLs for reliable loading
const logoSvg = 'data:image/svg+xml;base64,' + btoa(`
  <svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
    <circle cx="32" cy="32" r="30" fill="#ff6b6b"/>
  </svg>
`);

// Solution 2: Check CORS settings for external images
// Ensure images are served with proper CORS headers

// Solution 3: Verify file paths are correct and accessible
const testImage = new Image();
testImage.onload = () => console.log('Image loaded successfully');
testImage.onerror = () => console.error('Failed to load image');
testImage.src = '/path/to/your/image.png';

Performance Issues

Problem: Slow performance with many particles

// Solution: Optimize settings for better performance
await window.fireConfetti(images, {
  particleCount: 30, // Reduce particle count
  duration: 2000,    // Shorter duration
  imageSize: { width: 15, height: 15 }, // Smaller particles
});

Mobile Compatibility

Problem: Effects too intense on mobile devices

// Solution: Detect mobile and adjust accordingly
const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

const particleCount = isMobile ? 25 : 100;
const duration = isMobile ? 2000 : 4000;

await window.fireShapeConfetti({
  particleCount,
  duration,
  imageSize: { width: isMobile ? 12 : 20, height: isMobile ? 12 : 20 }
});

Path Issues

Problem: Script not loading or functions not available

// Solution: Check if library is loaded before using
if (typeof window.fireConfetti === 'function') {
  await window.fireConfetti(images, options);
} else {
  console.error('Image Confetti library not loaded - check script src path');
}

// For different folder structures, adjust the path:
// <script src="src/index.js"></script>           <!-- If in same folder -->
// <script src="dist/index.js"></script>          <!-- If using built version -->
// <script src="../long-confetti/src/index.js"></script>  <!-- If in parent folder -->

📄 License

MIT License - see LICENSE file for details

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b my-new-feature
  3. Commit changes: git commit -am 'Add some feature'
  4. Push to branch: git push origin my-new-feature
  5. Submit a pull request

🙋 Support

🌟 Changelog

v1.0.0

  • NEW: Support for up to 5 custom PNG/SVG images as confetti particles
  • NEW: Built-in emoji presets (🎉⭐❤️🌟🎈)
  • NEW: Built-in geometric shape presets (circles, squares, triangles, stars)
  • NEW: Physics engine with realistic gravity, wind, and velocity simulation
  • 🎯 NEW: Flexible launch origins (fire from any screen position)
  • 📐 NEW: Highly customizable options (size, rotation, duration, particle count)
  • 🚀 NEW: Performance-optimized DOM manipulation with RAF animation
  • 🔧 NEW: Full TypeScript support with comprehensive type definitions
  • 🌐 NEW: Direct browser usage without build tools required
  • 📱 NEW: Responsive design that works on all screen sizes and devices

📋 Quick Reference

Function Purpose Example
window.fireConfetti(images, options) Custom images await window.fireConfetti(['/logo.png'], {particleCount: 50})
window.fireEmojiConfetti(options) Default emojis await window.fireEmojiConfetti({particleCount: 100})
window.fireShapeConfetti(options) Geometric shapes await window.fireShapeConfetti({duration: 4000})
new window.ImageConfetti() Advanced usage const confetti = new window.ImageConfetti(); await confetti.fire(options);

Quick Usage Reference

Method Use Case Code
CDN (Recommended) No Node.js needed <script src="https://cdn.jsdelivr.net/npm/long-confetti@1.0.0/long-confetti.cdn.js"></script>
unpkg CDN Alternative CDN <script src="https://unpkg.com/long-confetti@1.0.0/long-confetti.cdn.js"></script>
Local CDN File Downloaded file <script src="long-confetti.cdn.js"></script>
Source File Development <script src="src/index.js"></script>
NPM Module Build tools import { fireConfetti } from "long-confetti"

Made with ❤️ for celebrations everywhere! 🎉