Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } body { margin: 0 auto; height: 100vh; background: linear-gradient(45deg, #000000,#232323); } .bubblePopper { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); height: 100%; width: 100%; cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewbox='0 0 28 28' height='28' width='28'%3E%3Cpath d='M 2 2 l23 23' fill='none' stroke='rgba(0,0,0,0.5)' stroke-width='1.6' stroke-linecap='round' /%3E%3Cpath d='M 2 2 l23 23' fill='none' stroke='%23ccc' stroke-width='1.4' stroke-linecap='round' /%3E%3Ccircle cx='24' cy='24' r='3.3' fill='rgba(0,0,0,0.5)' /%3E%3Ccircle cx='24' cy='24' r='3' fill='orange' /%3E%3C/svg%3E") 2 2, auto; } } .mouth, .eyeL, .eyeR { transition: 200ms; } #reset { position: fixed; bottom: 20px; right: 20px; height: 70px; width: 70px; border-radius: 50%; box-shadow: 0px 4px 6px rgba(0,0,0,0.8); border: none; cursor: pointer; font-weight: bold; background: #d1cfe2; } #reset > span { user-select: none; pointer-events: none; } #reset:hover { transform:translateY(-2px); box-shadow: 0px 6px 8px rgba(0,0,0,0.6); border: 2px solid #52b2cf; }
console.log("Event Fired") const randInt = (min, max) => { return Math.floor(Math.random() * (max - min + 1)) + min; } function addListeners() { const bubbles = document.querySelectorAll('.bubble'); // add listener to all bubbles for (let i = 0; i < bubbles.length; i++) { bubbles[i].addEventListener('click', (e) => { handleBubbleClick(bubbles[i]); }); bubbles[i].addEventListener('mouseover', (e) => { handleBubbleClick(bubbles[i]); }); bubbles[i].addEventListener('touchstart', (e) => { e.preventDefault(); // Prevent default touch behavior handleBubbleClick(bubbles[i]); }); } } function handleBubbleClick(bubble) { const maskCircle = document.getElementById(bubble.id + 'mask'); const hole = maskCircle.querySelector('.r'); let animDur = parseInt(hole.getAttribute('dur')); let hh = window.innerHeight; let ww = window.innerWidth; let xOff = Math.floor(ww/90); let yOff = Math.floor(hh/90); maskCircle.setAttribute('transform', `translate(${randInt(-xOff, xOff)} ${randInt(-yOff, yOff)})`); // make it unclickable after clicked bubble.setAttribute('user-select', 'none'); bubble.setAttribute('pointer-events', 'none'); let br = bubble.getAttribute('r') * 1; bubble.setAttribute('r', br * 1.11); hole.beginElement(); confetti(bubble, {type: 'circle', colors:['rgba(255,255,255,0.3)', 'rgba(255,255,255,0.25)', 'rgba(255,255,255,0.2)', 'rgba(255,255,255,0.15)', 'rgba(255,255,255,0.1)'], flakes: randInt(5,10), spin: true, fadeout: true, angle: 180, spread: xOff * 20, drop: yOff * 15, speed: 2000}); setTimeout(() => { bubble.remove(); maskCircle.remove(); if (document.querySelectorAll('#bubbleArea > circle').length === 0) { confetti(document.querySelector('.bubblePopper'), {flakes: 150, spin: true, fadeout: true, drop: window.innerHeight, spread: window.innerWidth, speed: 10000}); } }, animDur); } function createBubbles() { let hh = window.innerHeight; let ww = window.innerWidth; let numBubbles = randInt(12, 22); document.querySelector('.bubblePopper').setAttribute('viewBox', `0 0 ${ww} ${hh}`); document.querySelector('#bubbleArea').innerHTML = ''; document.querySelector('#bubbleDef').innerHTML = ''; let rr = randInt(0, 255), gg = randInt(0, 255), bb = randInt(0, 255); const getUUID = () => { let d = new Date().getTime(); let uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace( /[xy]/g, function (c) { let r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == "x" ? r : (r & 0x3) | 0x8).toString(16); } ); return uuid; }; for (let j=0; j
` } for (let i=0; i
`; let bubble = `
`; let wrapper = document.createElementNS("http://www.w3.org/2000/svg", "svg"); let wrapper1 = document.createElementNS("http://www.w3.org/2000/svg", "svg"); wrapper.innerHTML = `${bubble}`; wrapper1.innerHTML = `${maskBubble}`; let maskBubble1 = wrapper1.firstChild; let bubble1 = wrapper.firstChild; document.querySelector('#bubbleDef').appendChild(maskBubble1); document.querySelector('#bubbleArea').appendChild(bubble1); } addListeners(); } createBubbles(); document.querySelector('#reset').addEventListener('click', createBubbles);