luminomorphism
Version:
A UI design system built around light, blur, ambient motion and perceptual feedback.
67 lines (61 loc) • 3.06 kB
JavaScript
class LPulseBubble extends HTMLElement{constructor(){super(),this.shadow=this.attachShadow({mode:"open"}),this.render()}static get observedAttributes(){return["count","color","speed","size","floating"]}attributeChangedCallback(a,t,s){t!==s&&this.render()}render(){const a=parseInt(this.getAttribute("count"))||8,t=this.getAttribute("color")||"#00ffff",s=this.getAttribute("speed")||"medium",o=parseInt(this.getAttribute("size"))||20,r=this.getAttribute("floating")!=="false";this.shadow.innerHTML="";const n=document.createElement("div");n.className="bubble-container";const i=document.createElement("style");i.textContent=`
.bubble-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
z-index: 1;
}
.bubble {
position: absolute;
width: ${o}px;
height: ${o}px;
background: ${t};
opacity: 0.3;
border-radius: 50%;
/* \xCEnlocuit blur cu box-shadow pentru performan\u021B\u0103 */
box-shadow: 0 0 15px ${t}, 0 0 30px ${t}40;
animation: pulse infinite ease-in-out;
${r?"animation: pulse-float infinite ease-in-out;":"animation: pulse infinite ease-in-out;"}
}
.slow { animation-duration: 8s; }
.medium { animation-duration: 5s; }
.fast { animation-duration: 2.5s; }
@keyframes pulse {
0% { transform: scale(1); opacity: 0.3; }
50% { transform: scale(2.5); opacity: 0.05; }
100% { transform: scale(1); opacity: 0.3; }
}
/* Anima\u021Bie combinat\u0103: pulse + float */
@keyframes pulse-float {
0% {
transform: scale(1) translateY(0px);
opacity: 0.3;
}
25% {
transform: scale(1.8) translateY(-10px);
opacity: 0.15;
}
50% {
transform: scale(2.5) translateY(-15px);
opacity: 0.05;
}
75% {
transform: scale(1.8) translateY(-10px);
opacity: 0.15;
}
100% {
transform: scale(1) translateY(0px);
opacity: 0.3;
}
}
/* Responsive adjustments */
@media (max-width: 768px) {
.bubble {
box-shadow: 0 0 8px ${t}, 0 0 15px ${t}40;
}
}
`;for(let l=0;l<a;l++){const e=document.createElement("div");e.className=`bubble ${s}`,e.style.top=Math.random()*90+"%",e.style.left=Math.random()*90+"%";const u=Math.random()*3;e.style.animationDelay=u+"s";const c=.7+Math.random()*.6;e.style.transform=`scale(${c})`,n.appendChild(e)}this.shadow.appendChild(i),this.shadow.appendChild(n)}refresh(){this.render()}pause(){this.shadow.querySelectorAll(".bubble").forEach(t=>{t.style.animationPlayState="paused"})}resume(){this.shadow.querySelectorAll(".bubble").forEach(t=>{t.style.animationPlayState="running"})}}customElements.define("l-pulse-bubble",LPulseBubble),typeof module<"u"&&module.exports&&(module.exports=LPulseBubble);