//import { Fireworks } from '/js/fireworks-js@2.x/dist/fireworks.js'; //console.log(Fireworks); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) class EffectsObj { constructor() { this.particlesContainer = null; this.fireworksObj = null; } init() { window.myConfetti = confetti.create(document.getElementById('myConfettiCanvas'), { resize: true, useWorker: true }); // Force this canvas on top of Bootstrap modal let myConfettiObj = $('#myConfettiCanvas'); if (myConfettiObj.length === 0) { $('body').append(''); myConfettiObj = $('#myConfettiCanvas'); } const c = document.getElementById('myConfettiCanvas'); c.style.position = 'fixed'; c.style.top = 0; c.style.left = 0; c.style.zIndex = 999999; // OVER the modal c.style.pointerEvents = 'none'; // fireworks /* if ($("#tsparticles").length === 0) { $("body").append(`
`); } // Load the tsParticles container with configuration tsParticles.load("tsparticles", { background: { color: "transparent" }, particles: { number: { value: 0 }, // No initial particles color: { value: ["#ff0000", "#ffff00", "#00ffff", "#ffffff"] }, shape: { type: "circle" }, opacity: { value: { min: 0.6, max: 1 } }, size: { value: { min: 2, max: 4 } }, move: { enable: true, speed: { min: 10, max: 25 }, direction: "none", outModes: { default: "destroy" } }, life: { count: 1, duration: { value: 2 } } }, detectRetina: true }).then((loadedContainer) => { this.particlesContainer = loadedContainer; console.log(this.particlesContainer.version); console.log("Particles container initialized:", this.particlesContainer); });*/ // Once the container is initialized, you can now safely add emitters //console.log("Particles container initialized:", this.particlesContainer); //console.log(this.particlesContainer.version); } confetti(obj) { /* const modalConfetti = confetti.create( document.getElementById('modalConfetti'), { resize: true, useWorker: true } )*/ let currObj = $(obj); if (currObj.data('target-obj')) { currObj = $(currObj.data('target-obj')); } const offset = currObj.offset(); const width = currObj.outerWidth(); const height = currObj.outerHeight(); // Convert to confetti origin (0–1 range) const origin = { //x: (offset.left + width / 2) / $(window).width(), //y: (offset.top + height / 2) / $(window).height() x: (offset.left + width / 2) / $(window).width(), y: (offset.top + height / 2) / $(window).height() }; confetti({ particleCount: 200, spread: 90, zIndex: 999999, origin: origin }); /* setTimeout(() => { const canvas = document.querySelector("canvas.confetti-canvas"); if (canvas) { canvas.style.position = "fixed"; canvas.style.zIndex = "999999"; canvas.style.pointerEvents = "none"; // so it doesn't block clicks } }, 0);*/ } confettiStars(obj) { let currObj = $(obj); if (currObj.data('target-obj')) { currObj = $(currObj.data('target-obj')); } const offset = currObj.offset(); const width = currObj.outerWidth(); const height = currObj.outerHeight(); // Convert to confetti origin (0–1 range) const origin = { x: (offset.left + width / 2) / $(window).width(), y: (offset.top + height / 2) / $(window).height() }; var defaults = { spread: 360, ticks: 50, gravity: 0, decay: 0.94, startVelocity: 30, zIndex: 999999, colors: ['FFE400', 'FFBD00', 'E89400', 'FFCA6C', 'FDFFB8'] }; function shoot() { confetti({ ...defaults, particleCount: 40, scalar: 1.2, shapes: ['star'], origin: origin }); confetti({ ...defaults, particleCount: 10, scalar: 0.75, shapes: ['circle'], origin: origin }); } setTimeout(shoot, 0); setTimeout(shoot, 100); setTimeout(shoot, 200); setTimeout(() => { const canvas = document.querySelector("canvas.confetti-canvas"); if (canvas) { canvas.style.position = "fixed"; canvas.style.zIndex = "999999"; canvas.style.pointerEvents = "none"; // so it doesn't block clicks } }, 0); } confettiSmiley(obj) { let currObj = $(obj); if (currObj.data('target-obj')) { currObj = $(currObj.data('target-obj')); } const offset = currObj.offset(); const width = currObj.outerWidth(); const height = currObj.outerHeight(); // Convert to confetti origin (0–1 range) const origin = { x: (offset.left + width / 2) / $(window).width(), y: (offset.top + height / 2) / $(window).height() }; var scalar = 2; var unicorn = confetti.shapeFromText({ text: '🦄', scalar }); var smiley = confetti.shapeFromText({ text: '😀', scalar }); var defaults = { spread: 360, ticks: 60, gravity: 0, decay: 0.9, startVelocity: 20, shapes: [smiley, unicorn, smiley], zIndex: 9999999, origin: origin, scalar }; function shoot() { confetti({ ...defaults, particleCount: 30 }); confetti({ ...defaults, particleCount: 5, flat: true }); confetti({ ...defaults, particleCount: 15, scalar: scalar / 2, shapes: ['circle'] }); } setTimeout(shoot, 0); setTimeout(shoot, 100); setTimeout(shoot, 200); } fireworks(obj) { let currObj = $(obj); if (currObj.data('target-obj')) { currObj = $(currObj.data('target-obj')); } const offset = currObj.offset(); const width = currObj.outerWidth(); const height = currObj.outerHeight(); // Convert to confetti origin (0–1 range) const origin = { x: (offset.left + width / 2) / $(window).width(), y: (offset.top + height / 2) / $(window).height() }; // Convert pixel coordinates to percentage (required by tsParticles) const xPercent = (obj.x / window.innerWidth) * 100; const yPercent = (obj.y / window.innerHeight) * 100; // Initialize library if (!this.fireworksObj) { if ($('#fireworks-overlay').length === 0) { $('body').append('
'); } const container = document.getElementById('fireworks-overlay'); this.fireworksObj = new Fireworks.Fireworks(container, { autoresize: true, opacity: 0.5, acceleration: 1.05, friction: 0.98, gravity: 1.5, particles: 100, traceLength: 3, explosion: 7, // --- THESE TWO LINES STOP AUTO-LAUNCHING --- //intensity: 0, //delay: { min: 0, max: 0 } }); this.fireworksObj.start(); } let btn = currObj[0]; const rect = btn.getBoundingClientRect(); // Calculate center of button const centerX = rect.left + rect.width / 2; const startY = rect.top; // Convert X pixel to percentage for the library (0-100) const xPct = (centerX / window.innerWidth) * 100; /* this.fireworksObj.launch(4, { // The explosion destination (above the button) x: centerX + (Math.random() * 200 - 100), y: startY - (200 + Math.random() * 300), // The starting point (exactly at the button) rocketsPoint: { min: xPct, max: xPct } });*/ // A helper function to save space const shoot = (delayMs) => { setTimeout(() => { this.fireworksObj.launch(1, { x: centerX + (Math.random() * 200 - 100), // Random spread y: startY - (200 + Math.random() * 300), // Random height rocketsPoint: { min: xPct, max: xPct } }); }, delayMs); }; // Launch 4 fireworks at different times (in milliseconds) shoot(0); // Immediate shoot(400); // 0.4 seconds later shoot(800); // 0.8 seconds later shoot(1200); // 1.2 seconds later /* for (let iterator = 0; iterator < 5; iterator ++) { // Launch rocket let countLaunch = 0; console.log(countLaunch); setTimeout(function() { this.fireworksObj.launch(4, { // The explosion destination (above the button) x: centerX + (Math.random() * 200 - 100), y: startY - (200 + Math.random() * 300), // The starting point (exactly at the button) rocketsPoint: { min: xPct, max: xPct } }); countLaunch ++; }, Math.random() * (2000 - 500) + 500); }*/ } fireworksOld(obj) { let currObj = $(obj); if (currObj.data('target-obj')) { currObj = $(currObj.data('target-obj')); } const offset = currObj.offset(); const width = currObj.outerWidth(); const height = currObj.outerHeight(); // Convert to confetti origin (0–1 range) const origin = { x: (offset.left + width / 2) / $(window).width(), y: (offset.top + height / 2) / $(window).height() }; // Convert pixel coordinates to percentage (required by tsParticles) const xPercent = (obj.x / window.innerWidth) * 100; const yPercent = (obj.y / window.innerHeight) * 100; // Load the particles effect // Add an emitter at the specified position console.log(this.particlesContainer.version); console.log(this.particlesContainer); this.particlesContainer.addEmitter({ position: { x: xPercent, y: yPercent }, rate: { quantity: 0, delay: 0 }, // Single burst life: { count: 1, duration: 0.1 }, // Single burst duration emitters: { direction: "none" }, burst: { count: 80, delay: 0 } // Number of particles in the burst }); } async runEffect(obj, single) { let jObj = $(obj); let effect = jObj.data('effect'); let effects = typeof single == 'boolean' && single === true ? null : jObj.data('effects'); let effectArray = new Array(); if (typeof effects == 'string' && effects.length > 0) { effectArray = effects.split(','); } else if (typeof effect == 'string' || typeof effect == 'number') { effectArray.push(effect); } for (const effectIndex in effectArray) { let effectId = parseInt(effectArray[effectIndex]); console.log(effectIndex); switch (effectId) { case 1: this.confetti(obj); break; case 2: this.confettiStars(obj); break; case 3: this.confettiSmiley(obj); break; case 4: this.fireworks(obj); break; } await this.sleep(2000); } } sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } class ShoutOut { sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } chooseEffect(obj) { let jObj = $(obj); $('.btn-effect').not(obj).addClass('btn-outline-secondary'); $('.btn-effect').not(obj).removeClass('btn-secondary').removeClass('effect-selected'); jObj.addClass('btn-secondary').addClass('effect-selected'); jObj.removeClass('btn-outline-secondary'); } saveEffect(obj) { let jObj = $(obj); let shoutOptCont = jObj.closest('.shout-out-opt'); let effectSelected = shoutOptCont.find('.effect-selected'); if (!effectSelected.length) { let tooltip = bootstrap.Tooltip.getInstance(jObj); if (tooltip) { tooltip.dispose(); } tooltip = new bootstrap.Tooltip(jObj, { title: jObj.data('error-tip'), trigger: 'manual', customClass: 'error-tooltip', placement: 'top' }) tooltip.show(); setTimeout(function() { tooltip.hide(); }, 3000); return; } let effect = effectSelected.data('effect'); let athleteId = jObj.data('athlete-id'); // saved $.ajax({ url: '/site/save-effect', method: 'POST', data: {athleteId: athleteId, effect: effect}, dataType: 'json', success: function(data) { if (data.success) { lightBoxObject.fillContent('Saved Shoutout Successfully!', ''); } } }); } payEffect(obj) { let jObj = $(obj); let shoutOptCont = jObj.closest('.shout-out-opt'); let effectSelected = shoutOptCont.find('.effect-selected'); if (!effectSelected.length) { let tooltip = bootstrap.Tooltip.getInstance(jObj); if (tooltip) { tooltip.dispose(); } tooltip = new bootstrap.Tooltip(jObj, { title: jObj.data('error-tip'), trigger: 'manual', customClass: 'error-tooltip', placement: 'top' }) tooltip.show(); setTimeout(function() { tooltip.hide(); }, 3000); return; } let athleteId = jObj.data('athlete-id'); let effect = effectSelected.data('effect'); window.location = '/payment/checkout?item=effect&effect=' + effect + '&athleteId=' + athleteId; } } let EffectsObject; let ShoutOutObject; $(document).ready(function(){ EffectsObject = new EffectsObj(); EffectsObject.init(); ShoutOutObject = new ShoutOut(); })