UNPKG

v12-ui

Version:

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

2 lines (1 loc) 6.9 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("react/jsx-runtime"),x=require("react"),E=require("../utils/utils.cjs");class y{canvas;ctx;particles=[];mouse=null;animationId=null;dpr;config;imageElement=null;constructor(e,i){this.canvas=e;const a=e.getContext("2d",{willReadFrequently:!0});if(!a)throw new Error("No se pudo obtener el contexto 2D del canvas");this.ctx=a,this.dpr=window.devicePixelRatio||1,this.config=i,this.setupCanvas(),this.initializeEffect()}async initializeEffect(){try{this.config.imageUrl?(console.log("MagicLogo: Cargando imagen desde URL:",this.config.imageUrl),await this.loadImage(this.config.imageUrl)):this.config.svgContent?(console.log("MagicLogo: Cargando SVG como imagen"),await this.loadSVGAsImage(this.config.svgContent)):this.config.imageElement&&(console.log("MagicLogo: Cargando elemento de imagen existente"),await this.loadImageElement(this.config.imageElement)),console.log("MagicLogo: Imagen cargada exitosamente, generando partículas..."),this.generateParticles(),this.setupEventListeners(),this.animate=this.animate.bind(this),this.animate()}catch(e){console.error("MagicLogo: Error al inicializar el efecto:",e)}}async loadImage(e){return await new Promise((i,a)=>{const t=new Image,n=()=>{this.imageElement=t,t.removeEventListener("load",n),t.removeEventListener("error",s),i()},s=o=>{t.removeEventListener("load",n),t.removeEventListener("error",s),a(new Error(`Error al cargar la imagen desde URL: ${e} - ${o.type}`))};t.addEventListener("load",n),t.addEventListener("error",s),t.crossOrigin="anonymous",t.src=e,setTimeout(()=>{t.removeEventListener("load",n),t.removeEventListener("error",s),a(new Error(`Timeout: La imagen desde URL ${e} tardó demasiado en cargar`))},1e4)})}async loadImageElement(e){return await new Promise((i,a)=>{if(e.complete&&e.naturalWidth>0)this.imageElement=e,i();else{const t=()=>{this.imageElement=e,e.removeEventListener("load",t),e.removeEventListener("error",n),i()},n=s=>{e.removeEventListener("load",t),e.removeEventListener("error",n),a(new Error(`Error al cargar la imagen: ${s.type}`))};e.addEventListener("load",t),e.addEventListener("error",n),setTimeout(()=>{e.removeEventListener("load",t),e.removeEventListener("error",n),a(new Error("Timeout: La imagen tardó demasiado en cargar"))},1e4)}})}async loadSVGAsImage(e){return await new Promise((i,a)=>{const t=new Blob([e],{type:"image/svg+xml"}),n=URL.createObjectURL(t),s=new Image,o=()=>{this.imageElement=s,URL.revokeObjectURL(n),s.removeEventListener("load",o),s.removeEventListener("error",r),i()},r=l=>{URL.revokeObjectURL(n),s.removeEventListener("load",o),s.removeEventListener("error",r),a(new Error(`Error al cargar SVG como imagen: ${l.type}`))};s.addEventListener("load",o),s.addEventListener("error",r),s.crossOrigin="anonymous",s.src=n,setTimeout(()=>{URL.revokeObjectURL(n),s.removeEventListener("load",o),s.removeEventListener("error",r),a(new Error("Timeout: El SVG tardó demasiado en cargar"))},1e4)})}setupCanvas(){const e=this.canvas.getBoundingClientRect();this.canvas.width=e.width*this.dpr,this.canvas.height=e.height*this.dpr,this.canvas.style.width=`${e.width}px`,this.canvas.style.height=`${e.height}px`,this.ctx.scale(this.dpr,this.dpr),this.ctx.imageSmoothingEnabled=!0,this.ctx.imageSmoothingQuality&&(this.ctx.imageSmoothingQuality="high")}createImageMask(){return this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.imageElement&&this.drawImageToCanvas(this.imageElement),this.ctx.getImageData(0,0,this.canvas.width,this.canvas.height)}drawImageToCanvas(e){const i=this.canvas.width/this.dpr,a=this.canvas.height/this.dpr,n=Math.min(i/e.naturalWidth,a/e.naturalHeight)*.8,s=e.naturalWidth*n,o=e.naturalHeight*n,r=(i-s)/2,l=(a-o)/2;this.ctx.drawImage(e,r,l,s,o)}extractPositions(e){const i=[],{data:a,width:t,height:n}=e,o=Math.max(1,4);let r=0;for(let c=0;c<a.length;c+=4){const[h,g,d,m]=a.slice(c,c+4);m>50&&(h<220||g<220||d<220)&&r++}const l=Math.max(1,Math.floor(Math.sqrt(r/(this.config.particles||6e3)))),v=Math.min(o,l);for(let c=0;c<n;c+=v)for(let h=0;h<t;h+=v){const g=(c*t+h)*4,[d,m,u,L]=a.slice(g,g+4);L>50&&(d<220||m<220||u<220)&&i.push({x:h/this.dpr,y:c/this.dpr,color:`rgb(${d},${m},${u})`})}return i}generateParticles(){if(!this.imageElement){console.warn("No hay imagen cargada para generar partículas");return}const e=this.createImageMask(),i=this.extractPositions(e);if(i.length===0){console.warn("No se encontraron píxeles visibles en la imagen");return}const a=Math.max(this.canvas.width,this.canvas.height)*2;this.particles=i.map((t,n)=>({tx:t.x,ty:t.y,x:t.x+(Math.random()-.5)*a,y:t.y+(Math.random()-.5)*a,vx:0,vy:0,color:t.color,phase:Math.random()*Math.PI*2,age:0,order:n}))}updateParticle(e){const i=e.tx-e.x,a=e.ty-e.y;if(this.mouse){const s=this.mouse.x-e.x,o=this.mouse.y-e.y,r=Math.hypot(s,o),v=e.order*.08,h=(r-v)*.1;r>0&&(e.vx+=s/r*h,e.vy+=o/r*h)}const t=.04,n=.73;e.vx+=i*t,e.vy+=a*t,e.vx*=n,e.vy*=n,e.x+=e.vx,e.y+=e.vy}drawParticles(){const e=this.canvas.width/this.dpr,i=this.canvas.height/this.dpr;this.ctx.clearRect(0,0,e,i);for(const a of this.particles){this.updateParticle(a),a.age+=1;const t=(Math.sin(a.phase+a.age*.15)+1)/2;this.ctx.fillStyle=this.config.color||a.color||"#fff",this.config.glow&&(this.ctx.globalAlpha=t),this.ctx.beginPath(),this.ctx.arc(a.x,a.y,this.config.dotSize,0,Math.PI*2),this.ctx.fill()}this.ctx.globalAlpha=1}handleMouseMove=e=>{const i=this.canvas.getBoundingClientRect();this.mouse={x:(e.clientX-i.left)*(this.canvas.width/this.dpr/i.width),y:(e.clientY-i.top)*(this.canvas.height/this.dpr/i.height)}};handleMouseLeave=()=>{this.mouse=null};animate(){this.drawParticles(),this.animationId=requestAnimationFrame(this.animate)}setupEventListeners(){this.canvas.addEventListener("mousemove",this.handleMouseMove),this.canvas.addEventListener("mouseleave",this.handleMouseLeave)}destroy(){this.canvas.removeEventListener("mousemove",this.handleMouseMove),this.canvas.removeEventListener("mouseleave",this.handleMouseLeave),this.animationId&&cancelAnimationFrame(this.animationId)}}function M({imageUrl:f,imageElement:e,svgContent:i,particles:a=750,dotSize:t=.9,repulsion:n=80,friction:s=.82,returnSpeed:o=.01,color:r,glow:l=!0,className:v,...c}){const h=x.useRef(null);return x.useEffect(()=>{const g=h.current;if(!g)return;if(e&&(!e.complete||e.naturalWidth===0)){console.warn("MagicLogo: imageElement no está completamente cargado");return}let d;if(f!=null)d={imageUrl:f};else if(e!=null)d={imageElement:e};else if(i!=null)d={svgContent:i};else{console.warn("MagicLogo: falta una fuente de imagen");return}const m={particles:a,dotSize:t,repulsion:n,friction:s,returnSpeed:o,color:r,glow:l,...d},u=new y(g,m);return()=>{u&&u.destroy()}},[f,e,i,a,t,n,s,o,r,l]),w.jsx("canvas",{ref:h,...c,className:E.cn("block mx-auto overflow-visible z-0 w-auto h-auto",v)})}exports.MagicMouseFollower=M;