A Astro blog hosted on Vercel

pat cheese confetti

Changed files
+61 -13
src
pages
+61 -13
src/pages/pat.astro
··· 6 <!doctype html> 7 <html lang="en"> 8 <head> 9 - <Head title={'🐀'} description={'Pat the rat'} /> 10 <style> 11 @keyframes squish { 12 0% { ··· 24 display: flex; 25 justify-content: center; 26 align-items: center; 27 } 28 29 body > main > img { ··· 45 <source src="/rat-squeak.mp3" type="audio/mp3" /> 46 </audio> 47 <main> 48 <Image 49 id={'pat'} 50 - alt="Pat the rat" 51 src={'/pat.webp'} 52 width={128} 53 height={128} 54 /> 55 </main> 56 <script> 57 - const pat = document.querySelector<HTMLImageElement>('img#pat'); 58 59 - pat?.addEventListener('click', () => { 60 - if (!pat) return; 61 const squeakAudio = new Audio('rat-squeak.mp3'); 62 63 - pat.style.animationName = 'none'; 64 - pat.offsetHeight; 65 66 - pat.style.animationName = 'squish'; 67 - pat.style.animationPlayState = 'running'; 68 squeakAudio.currentTime = 0; 69 squeakAudio.play(); 70 }); 71 72 - pat?.addEventListener('animationend', () => { 73 - if (!pat) return; 74 75 - pat.style.animationName = 'none'; 76 - pat.style.animationPlayState = 'paused'; 77 }); 78 </script> 79 </body>
··· 6 <!doctype html> 7 <html lang="en"> 8 <head> 9 + <Head title={'🐀'} description={'pat the rat'} /> 10 + <script 11 + defer 12 + src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.4/dist/confetti.browser.min.js" 13 + > 14 + </script> 15 <style> 16 @keyframes squish { 17 0% { ··· 29 display: flex; 30 justify-content: center; 31 align-items: center; 32 + gap: 8rem; 33 + } 34 + 35 + body > main > p#cheeses { 36 + display: flex; 37 + flex-direction: row; 38 + gap: 1rem; 39 + font-size: 2rem; 40 + } 41 + 42 + body > main > p#cheeses[data-cheeses='0'] { 43 + visibility: hidden; 44 + } 45 + 46 + body > main > p#cheeses::after { 47 + content: attr(data-cheeses); 48 } 49 50 body > main > img { ··· 66 <source src="/rat-squeak.mp3" type="audio/mp3" /> 67 </audio> 68 <main> 69 + <p id="cheeses" data-cheeses="0">🧀</p> 70 <Image 71 id={'pat'} 72 + alt="pat the rat" 73 src={'/pat.webp'} 74 width={128} 75 height={128} 76 /> 77 </main> 78 <script> 79 + let cheeses = 0; 80 + const $PAT = document.querySelector<HTMLImageElement>('img#pat'); 81 + const $CHEESES = 82 + document.querySelector<HTMLParagraphElement>('p#cheeses'); 83 + const cheese = confetti.shapeFromText({ text: '🧀', scalar: 5 }); 84 85 + window.addEventListener('load', () => { 86 + window.cookieStore.get('cheeses').then((item) => { 87 + if (!$CHEESES) return; 88 + cheeses = parseInt(item?.value ?? '0'); 89 + $CHEESES.setAttribute('data-cheeses', cheeses.toString()); 90 + }); 91 + }); 92 + 93 + $PAT?.addEventListener('click', () => { 94 + if (!$PAT) return; 95 + if (!$CHEESES) return; 96 const squeakAudio = new Audio('rat-squeak.mp3'); 97 98 + $PAT.style.animationName = 'none'; 99 + $PAT.offsetHeight; 100 101 + $PAT.style.animationName = 'squish'; 102 + $PAT.style.animationPlayState = 'running'; 103 squeakAudio.currentTime = 0; 104 squeakAudio.play(); 105 + 106 + cheeses += 1; 107 + $CHEESES.setAttribute('data-cheeses', cheeses.toString()); 108 + window.cookieStore.set('cheeses', cheeses.toString()); 109 + 110 + if (cheeses % 100 === 0) { 111 + confetti({ 112 + particleCount: cheeses, 113 + spread: 360, 114 + shapes: [cheese], 115 + scalar: 5, 116 + }); 117 + } 118 }); 119 120 + $PAT?.addEventListener('animationend', () => { 121 + if (!$PAT) return; 122 123 + $PAT.style.animationName = 'none'; 124 + $PAT.style.animationPlayState = 'paused'; 125 }); 126 </script> 127 </body>