UNPKG

v12-ui

Version:

A React component library with a focus on utility-first design and accessibility.

2 lines (1 loc) 3.88 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("react/jsx-runtime"),u=require("react"),g=require("../Hooks/useDataTheme.cjs");class m{canvas;ctx;particles=[];mouse=null;animationId=null;dpr;config;constructor(t,e){this.canvas=t;const i=t.getContext("2d");if(!i)throw new Error("No se pudo obtener el contexto 2D del canvas");this.ctx=i,this.dpr=window.devicePixelRatio||1,this.config=e,this.setupCanvas(),this.generateParticles(),this.animate=this.animate.bind(this),this.animate()}setupCanvas(){const t=this.canvas.getBoundingClientRect();this.canvas.width=t.width*this.dpr,this.canvas.height=t.height*this.dpr,this.canvas.style.width=`${t.width}px`,this.canvas.style.height=`${t.height}px`,this.ctx.scale(this.dpr,this.dpr),this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality&&(this.ctx.imageSmoothingQuality="high")}createTextMask(){return this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.font=`bold ${this.config.fontSize||80}px ${this.config.fontFamily||"sans-serif"}`,this.ctx.textAlign="center",this.ctx.textBaseline="middle",this.ctx.fillStyle=`${this.config.textColor||"#fff"}`,this.ctx.fillText(this.config.text,this.canvas.width/2,this.canvas.height/2),this.ctx.getImageData(0,0,this.canvas.width,this.canvas.height)}extractPositions(t){const e=[],i=t.width*t.height,n=Math.max(1,Math.floor(Math.sqrt(i/this.config.particles)));for(let h=0;h<t.height;h+=n)for(let s=0;s<t.width;s+=n){const a=(h*t.width+s)*4;t.data[a+3]>128&&e.push({x:s,y:h})}return e}generateParticles(){const t=this.createTextMask(),i=this.extractPositions(t).sort(()=>Math.random()-.5);this.particles=i.slice(0,Math.min(this.config.particles,i.length)).map(n=>({tx:n.x,ty:n.y,x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:0,vy:0}))}updateParticle(t){const e=t.tx-t.x,i=t.ty-t.y;if(t.vx+=e*this.config.returnSpeed,t.vy+=i*this.config.returnSpeed,t.vx*=this.config.friction,t.vy*=this.config.friction,t.x+=t.vx,t.y+=t.vy,this.mouse){const n=this.mouse.x-t.x,h=this.mouse.y-t.y,s=Math.hypot(n,h);if(s<this.config.repulsion&&s>0){const a=(this.config.repulsion-s)/this.config.repulsion,c=10;t.vx-=n/s*a*c,t.vy-=h/s*a*c}t.vx+=e*this.config.returnSpeed*.5,t.vy+=i*this.config.returnSpeed*.5}else t.vx+=e*this.config.returnSpeed,t.vy+=i*this.config.returnSpeed}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);for(const t of this.particles)this.updateParticle(t),this.ctx.fillStyle=`${this.config.textColor||"#fff"}`,this.ctx.beginPath(),this.ctx.arc(t.x,t.y,this.config.dotSize,0,Math.PI*2),this.ctx.fill()}handleMouseMove=t=>{const e=this.canvas.getBoundingClientRect();this.mouse={x:(t.clientX-e.left)*(this.canvas.width/e.width),y:(t.clientY-e.top)*(this.canvas.height/e.height)}};handleMouseLeave=()=>{this.mouse=null};animate(){this.drawParticles(),this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseleave",this.handleMouseLeave),this.animationId=requestAnimationFrame(this.animate)}destroy(){this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseleave",this.handleMouseLeave),this.animationId&&cancelAnimationFrame(this.animationId)}}function y({text:o="Magic Text",particles:t=1e5,dotSize:e=1.5,repulsion:i=100,friction:n=.82,returnSpeed:h=.01,fontFamily:s="sans-serif",fontSize:a=80,textColor:c}){const{theme:r}=g.useDataTheme(),l=c||(r==="dark"?"#fff":"#000");console.log("Theme:",r,"Color detected:",l);const d=u.useRef(null);return u.useEffect(()=>{const f=d.current;if(!f)return;const x=new m(f,{text:o,particles:t,dotSize:e,repulsion:i,friction:n,returnSpeed:h,fontFamily:s,fontSize:a,textColor:l});return()=>{x&&x.destroy()}},[o,t,e,i,n,h,s,a,r,c]),v.jsx("canvas",{ref:d,className:"block mx-auto",style:{width:"100%",height:"100%"}})}exports.MagicText=y;