Code Playground
import { random, range } from 'lodash'; import './reset.css'; import './styles.css'; const PRECONFIGURED_PARTICLES = [ { angle: 210, distance: 55, }, { angle: 234, distance: 30, }, { angle: 225, distance: 75, }, { angle: 240, distance: 50, }, ]; window.addEventListener('click', (event) => { const x = event.clientX; const y = event.clientY; // Skip this effect for folks with motion sensitivities. // (In the course, we explore the accessibility implicationsof // this effect in much more detail!) const motionEnabled = window.matchMedia( '(prefers-reduced-motion: no-preference)' ).matches; if (!motionEnabled) { return; } const particles = []; range(4).forEach((index) => { const particle = document.createElement('img'); particle.setAttribute('alt', ''); particle.setAttribute( 'src', 'https://sandpack-bundler.vercel.app/img/wand-sparkle.svg' ); particle.setAttribute('aria-hidden', 'true'); particle.classList.add('star'); particle.style.top = y + 'px'; particle.style.left = x + 'px'; // Grab the preconfigured angle/distance, but add a bit // of random variation: let { angle, distance } = PRECONFIGURED_PARTICLES[index]; angle += random(-8, 8); distance += random(-5, 5); // Other dynamic values, like spin and size: const rotation = random(-45, -270); const size = random(13, 18); particle.style.setProperty('--size', size + 'px') particle.style.setProperty('--angle', angle + 'deg'); particle.style.setProperty('--distance', distance + 'px'); particle.style.setProperty('--rotation', rotation + 'deg'); // Generate a travel duration. The “normalize” function is // used to derive the duration from the total distance traveled. // We add a small bit of randomness to that as well. particle.style.setProperty( '--pop-duration', normalize(distance, 20, 85, 1000, 1400) + random(-300, 300) + 'ms' ); // The fade transition settings are separate, and // generated here: particle.style.setProperty( '--fade-duration', random(700, 900) + 'ms' ); particle.style.setProperty( '--fade-delay', normalize(distance, 20, 85, 250, 500) + 'ms' ); document.body.appendChild(particle); particles.push(particle); }); // Clean up the particles after they’ve finished fading away: window.setTimeout( () => { particles.forEach((particle) => { particle.remove(); }); }, 3000 ); }); const normalize = ( number, currentScaleMin, currentScaleMax, newScaleMin, newScaleMax ) => { // FIrst, normalize the value between 0 and 1. const standardNormalization = (number - currentScaleMin) / (currentScaleMax - currentScaleMin); // Next, transpose that value to our desired scale. return ( (newScaleMax - newScaleMin) * standardNormalization + newScaleMin ); };