|
| 1 | +// Confetti.js - downloaded from https://www.cssscript.com/confetti-falling-animation/ |
| 2 | + |
| 3 | +var confetti = { |
| 4 | + maxCount: 150, //set max confetti count |
| 5 | + speed: 2, //set the particle animation speed |
| 6 | + frameInterval: 15, //the confetti animation frame interval in milliseconds |
| 7 | + alpha: 1.0, //the alpha opacity of the confetti (between 0 and 1, where 1 is opaque and 0 is invisible) |
| 8 | + gradient: false, //whether to use gradients for the confetti particles |
| 9 | + start: null, //call to start confetti animation (with optional timeout in milliseconds, and optional min and max random confetti count) |
| 10 | + stop: null, //call to stop adding confetti |
| 11 | + toggle: null, //call to start or stop the confetti animation depending on whether it's already running |
| 12 | + pause: null, //call to freeze confetti animation |
| 13 | + resume: null, //call to unfreeze confetti animation |
| 14 | + togglePause: null, //call to toggle whether the confetti animation is paused |
| 15 | + remove: null, //call to stop the confetti animation and remove all confetti immediately |
| 16 | + isPaused: null, //call and returns true or false depending on whether the confetti animation is paused |
| 17 | + isRunning: null, //call and returns true or false depending on whether the animation is running |
| 18 | +}; |
| 19 | + |
| 20 | +confetti.start = startConfetti; |
| 21 | +confetti.stop = stopConfetti; |
| 22 | +confetti.toggle = toggleConfetti; |
| 23 | +confetti.pause = pauseConfetti; |
| 24 | +confetti.resume = resumeConfetti; |
| 25 | +confetti.togglePause = toggleConfettiPause; |
| 26 | +confetti.isPaused = isConfettiPaused; |
| 27 | +confetti.remove = removeConfetti; |
| 28 | +confetti.isRunning = isConfettiRunning; |
| 29 | +var supportsAnimationFrame = |
| 30 | + window.requestAnimationFrame || |
| 31 | + window.webkitRequestAnimationFrame || |
| 32 | + window.mozRequestAnimationFrame || |
| 33 | + window.oRequestAnimationFrame || |
| 34 | + window.msRequestAnimationFrame; |
| 35 | +var colors = [ |
| 36 | + 'rgba(30,144,255,', |
| 37 | + 'rgba(107,142,35,', |
| 38 | + 'rgba(255,215,0,', |
| 39 | + 'rgba(255,192,203,', |
| 40 | + 'rgba(106,90,205,', |
| 41 | + 'rgba(173,216,230,', |
| 42 | + 'rgba(238,130,238,', |
| 43 | + 'rgba(152,251,152,', |
| 44 | + 'rgba(70,130,180,', |
| 45 | + 'rgba(244,164,96,', |
| 46 | + 'rgba(210,105,30,', |
| 47 | + 'rgba(220,20,60,', |
| 48 | +]; |
| 49 | +var streamingConfetti = false; |
| 50 | +var animationTimer = null; |
| 51 | +var pause = false; |
| 52 | +var lastFrameTime = Date.now(); |
| 53 | +var particles = []; |
| 54 | +var waveAngle = 0; |
| 55 | +var context = null; |
| 56 | + |
| 57 | +function resetParticle(particle, width, height) { |
| 58 | + particle.color = |
| 59 | + colors[(Math.random() * colors.length) | 0] + |
| 60 | + (confetti.alpha + ')'); |
| 61 | + particle.color2 = |
| 62 | + colors[(Math.random() * colors.length) | 0] + |
| 63 | + (confetti.alpha + ')'); |
| 64 | + particle.x = Math.random() * width; |
| 65 | + particle.y = Math.random() * height - height; |
| 66 | + particle.diameter = Math.random() * 10 + 5; |
| 67 | + particle.tilt = Math.random() * 10 - 10; |
| 68 | + particle.tiltAngleIncrement = Math.random() * 0.07 + 0.05; |
| 69 | + particle.tiltAngle = Math.random() * Math.PI; |
| 70 | + return particle; |
| 71 | +} |
| 72 | + |
| 73 | +function toggleConfettiPause() { |
| 74 | + if (pause) resumeConfetti(); |
| 75 | + else pauseConfetti(); |
| 76 | +} |
| 77 | + |
| 78 | +function isConfettiPaused() { |
| 79 | + return pause; |
| 80 | +} |
| 81 | + |
| 82 | +function pauseConfetti() { |
| 83 | + pause = true; |
| 84 | +} |
| 85 | + |
| 86 | +function resumeConfetti() { |
| 87 | + pause = false; |
| 88 | + runAnimation(); |
| 89 | +} |
| 90 | + |
| 91 | +function runAnimation() { |
| 92 | + if (pause) return; |
| 93 | + else if (particles.length === 0) { |
| 94 | + context.clearRect(0, 0, window.innerWidth, window.innerHeight); |
| 95 | + animationTimer = null; |
| 96 | + } else { |
| 97 | + var now = Date.now(); |
| 98 | + var delta = now - lastFrameTime; |
| 99 | + if (!supportsAnimationFrame || delta > confetti.frameInterval) { |
| 100 | + context.clearRect(0, 0, window.innerWidth, window.innerHeight); |
| 101 | + updateParticles(); |
| 102 | + drawParticles(context); |
| 103 | + lastFrameTime = now - (delta % confetti.frameInterval); |
| 104 | + } |
| 105 | + animationTimer = requestAnimationFrame(runAnimation); |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +function startConfetti(timeout, min, max) { |
| 110 | + var width = window.innerWidth; |
| 111 | + var height = window.innerHeight; |
| 112 | + window.requestAnimationFrame = (function () { |
| 113 | + return ( |
| 114 | + window.requestAnimationFrame || |
| 115 | + window.webkitRequestAnimationFrame || |
| 116 | + window.mozRequestAnimationFrame || |
| 117 | + window.oRequestAnimationFrame || |
| 118 | + window.msRequestAnimationFrame || |
| 119 | + function (callback) { |
| 120 | + return window.setTimeout(callback, confetti.frameInterval); |
| 121 | + } |
| 122 | + ); |
| 123 | + })(); |
| 124 | + var canvas = document.getElementById('confetti-canvas'); |
| 125 | + if (canvas === null) { |
| 126 | + canvas = document.createElement('canvas'); |
| 127 | + canvas.setAttribute('id', 'confetti-canvas'); |
| 128 | + canvas.setAttribute( |
| 129 | + 'style', |
| 130 | + 'display:block;z-index:999999;pointer-events:none;position:fixed;top:0' |
| 131 | + ); |
| 132 | + document.body.prepend(canvas); |
| 133 | + canvas.width = width; |
| 134 | + canvas.height = height; |
| 135 | + window.addEventListener( |
| 136 | + 'resize', |
| 137 | + function () { |
| 138 | + canvas.width = window.innerWidth; |
| 139 | + canvas.height = window.innerHeight; |
| 140 | + }, |
| 141 | + true |
| 142 | + ); |
| 143 | + context = canvas.getContext('2d'); |
| 144 | + } else if (context === null) context = canvas.getContext('2d'); |
| 145 | + var count = confetti.maxCount; |
| 146 | + if (min) { |
| 147 | + if (max) { |
| 148 | + if (min == max) count = particles.length + max; |
| 149 | + else { |
| 150 | + if (min > max) { |
| 151 | + var temp = min; |
| 152 | + min = max; |
| 153 | + max = temp; |
| 154 | + } |
| 155 | + count = |
| 156 | + particles.length + |
| 157 | + ((Math.random() * (max - min) + min) | 0); |
| 158 | + } |
| 159 | + } else count = particles.length + min; |
| 160 | + } else if (max) count = particles.length + max; |
| 161 | + while (particles.length < count) |
| 162 | + particles.push(resetParticle({}, width, height)); |
| 163 | + streamingConfetti = true; |
| 164 | + pause = false; |
| 165 | + runAnimation(); |
| 166 | + if (timeout) { |
| 167 | + window.setTimeout(stopConfetti, timeout); |
| 168 | + } |
| 169 | +} |
| 170 | + |
| 171 | +function stopConfetti() { |
| 172 | + streamingConfetti = false; |
| 173 | +} |
| 174 | + |
| 175 | +function removeConfetti() { |
| 176 | + stop(); |
| 177 | + pause = false; |
| 178 | + particles = []; |
| 179 | +} |
| 180 | + |
| 181 | +function toggleConfetti() { |
| 182 | + if (streamingConfetti) stopConfetti(); |
| 183 | + else startConfetti(); |
| 184 | +} |
| 185 | + |
| 186 | +function isConfettiRunning() { |
| 187 | + return streamingConfetti; |
| 188 | +} |
| 189 | + |
| 190 | +function drawParticles(context) { |
| 191 | + var particle; |
| 192 | + var x, y, x2, y2; |
| 193 | + for (var i = 0; i < particles.length; i++) { |
| 194 | + particle = particles[i]; |
| 195 | + context.beginPath(); |
| 196 | + context.lineWidth = particle.diameter; |
| 197 | + x2 = particle.x + particle.tilt; |
| 198 | + x = x2 + particle.diameter / 2; |
| 199 | + y2 = particle.y + particle.tilt + particle.diameter / 2; |
| 200 | + if (confetti.gradient) { |
| 201 | + var gradient = context.createLinearGradient( |
| 202 | + x, |
| 203 | + particle.y, |
| 204 | + x2, |
| 205 | + y2 |
| 206 | + ); |
| 207 | + gradient.addColorStop('0', particle.color); |
| 208 | + gradient.addColorStop('1.0', particle.color2); |
| 209 | + context.strokeStyle = gradient; |
| 210 | + } else context.strokeStyle = particle.color; |
| 211 | + context.moveTo(x, particle.y); |
| 212 | + context.lineTo(x2, y2); |
| 213 | + context.stroke(); |
| 214 | + } |
| 215 | +} |
| 216 | + |
| 217 | +function updateParticles() { |
| 218 | + var width = window.innerWidth; |
| 219 | + var height = window.innerHeight; |
| 220 | + var particle; |
| 221 | + waveAngle += 0.01; |
| 222 | + for (var i = 0; i < particles.length; i++) { |
| 223 | + particle = particles[i]; |
| 224 | + if (!streamingConfetti && particle.y < -15) |
| 225 | + particle.y = height + 100; |
| 226 | + else { |
| 227 | + particle.tiltAngle += particle.tiltAngleIncrement; |
| 228 | + particle.x += Math.sin(waveAngle) - 0.5; |
| 229 | + particle.y += |
| 230 | + (Math.cos(waveAngle) + particle.diameter + confetti.speed) * |
| 231 | + 0.5; |
| 232 | + particle.tilt = Math.sin(particle.tiltAngle) * 15; |
| 233 | + } |
| 234 | + if ( |
| 235 | + particle.x > width + 20 || |
| 236 | + particle.x < -20 || |
| 237 | + particle.y > height |
| 238 | + ) { |
| 239 | + if (streamingConfetti && particles.length <= confetti.maxCount) |
| 240 | + resetParticle(particle, width, height); |
| 241 | + else { |
| 242 | + particles.splice(i, 1); |
| 243 | + i--; |
| 244 | + } |
| 245 | + } |
| 246 | + } |
| 247 | +} |
| 248 | + |
| 249 | +export { startConfetti, stopConfetti, removeConfetti }; |
0 commit comments