js-waves-particles 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- var u=class{constructor(e={}){let{canvas:i,config:t}=e||{};this.canvas=null,this.ctx=null,this.mouseX=0,this.mouseY=0,this.targetMouseX=-1e3,this.targetMouseY=-1e3,this.mouseActive=!1,this.width=0,this.height=0,this.config=this._mergeDefaults(t||{}),this.time=0,this.isRunning=!1,this.particles=[],this._resizeTimeout=null;let s=typeof document<"u"&&i?typeof i=="string"?document.querySelector(i):i:null;if(s){this.canvas=s;let o=s.getBoundingClientRect();this.width=Math.round(o.width||window.innerWidth),this.height=Math.round(o.height||window.innerHeight)}else this._createAutoCanvas();try{if(!this.canvas)throw new Error("No canvas element available.");let o=this.canvas.getContext("2d");if(!o)throw new Error("Could not get 2D rendering context.");this.ctx=o}catch(o){console.error("[WaveParticles] Canvas error:",o);return}this._onMouseMove=this._onMouseMove.bind(this),this._onMouseLeave=this._onMouseLeave.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onResize=this._onResize.bind(this),typeof document<"u"&&(window.addEventListener("resize",this._onResize),this.resize()),this.initParticles(),this.start()}_mergeDefaults(e){let i={waves:[{amplitude:60,frequency:.003,speed:.006,yOffset:.55,color:"rgba(248, 225, 231, 0.25)",lineWidth:1.5,mouseInfluence:.45},{amplitude:50,frequency:.004,speed:.008,yOffset:.6,color:"rgba(212, 165, 165, 0.2)",lineWidth:1,mouseInfluence:.5},{amplitude:70,frequency:.0025,speed:.005,yOffset:.65,color:"rgba(255, 255, 255, 0.2)",lineWidth:1.5,mouseInfluence:.4},{amplitude:40,frequency:.0035,speed:.01,yOffset:.7,color:"rgba(201, 169, 110, 0.12)",lineWidth:1,mouseInfluence:.55}],particles:{countScale:8e3,maxCount:180},colors:{backgroundGradient:["#fdfcfb","#f7ede2","#e8d5d0"],particleColorPrefixes:["rgba(248, 225, 231,","rgba(212, 165, 165,","rgba(201, 169, 110,","rgba(255, 255, 255,","rgba(232, 213, 208,"],mouseGlowStops:[{offset:0,color:"rgba(255, 255, 255, 0.08)"},{offset:.5,color:"rgba(248, 225, 231, 0.04)"},{offset:1,color:"rgba(248, 225, 231, 0)"}]}},t={};for(let s in i)i.hasOwnProperty(s)&&(e&&e[s]?typeof i[s]=="object"&&!Array.isArray(i[s])&&typeof e[s]=="object"?t[s]=Object.assign({},i[s],e[s]):s==="waves"?t.waves=Array.isArray(e.waves)?[...e.waves]:JSON.parse(JSON.stringify(i.waves)):t[s]=e[s]:t[s]=JSON.parse(JSON.stringify(i[s])));return t}_createAutoCanvas(){if(typeof document>"u")return;let e=document.createElement("canvas");e.id="wave-particles-canvas",Object.assign(e.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",zIndex:"-1",pointerEvents:"none"});let i=document.body;i&&(i.insertBefore(e,i.firstChild),this.canvas=e,this.width=window.innerWidth,this.height=window.innerHeight)}_onResize(){this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this.resize()},250)}resize(){if(!this.canvas)return;let e=this.canvas.getBoundingClientRect(),i,t,s=parseInt(this.canvas.getAttribute("width"),10),o=parseInt(this.canvas.getAttribute("height"),10);s&&o?(i=Math.round(e.width||s),t=Math.round(e.height||o)):(i=window.innerWidth,t=window.innerHeight,!this.canvas.parentNode&&document.body&&document.body.insertBefore(this.canvas,document.body.firstChild)),this.width=i,this.height=t;let n=window.devicePixelRatio||1;this.canvas.width=Math.round(i*n),this.canvas.height=Math.round(t*n),this.ctx&&this.isRunning&&this.initParticles()}initParticles(){let{countScale:e=8e3,maxCount:i=180}=this.config.particles,t=Math.min(Math.floor(this.width*this.height/(e>0?e:8e3)),i);this.particles=Array.from({length:t},()=>({x:Math.random()*this.width,y:Math.random()*this.height,size:Math.random()*4+1.5,speedX:(Math.random()-.5)*.4,speedY:(Math.random()-.5)*.4,opacity:Math.random()*.6+.3,pulse:Math.random()*Math.PI*2,pulseSpeed:Math.random()*.025+.01,colorPrefix:this.config.colors.particleColorPrefixes[Math.floor(Math.random()*this.config.colors.particleColorPrefixes.length)]}))}_onMouseMove(e){let i=this.canvas.getBoundingClientRect();i&&(this.targetMouseX=e.clientX-i.left,this.targetMouseY=e.clientY-i.top,this.mouseActive=!0)}_onMouseLeave(){this.mouseActive=!1}_onTouchMove(e){let i=e.touches[0],t=this.canvas.getBoundingClientRect();!i||!t||(this.targetMouseX=i.clientX-t.left,this.targetMouseY=i.clientY-t.top,this.mouseActive=!0)}_onTouchEnd(){this.mouseActive=!1}drawBackground(e){let i=this.config.colors.backgroundGradient,t=e.createRadialGradient(this.width/2,this.height/2,0,this.width/2,this.height/2,Math.max(this.width,this.height)*.8);i.forEach((s,o)=>t.addColorStop(o/(i.length-1||1),s)),e.fillStyle=t,e.fillRect(0,0,this.width,this.height)}drawWaves(e){let i=this.mouseActive?this.mouseX/this.width:-1,t=this.mouseActive?this.mouseY/this.height:-1;for(let s=0;s<this.config.waves.length;s++){let o=this.config.waves[s],n=Math.max(2,o.layers||2);for(let h=0;h<n;h++){let r=(1-h/n)*.5+.5;e.beginPath();let d=this.height*o.yOffset+h*3,l=this.mouseActive?(i-.5)*(o.mouseInfluence||.45)*150:0;e.moveTo(0,this.height);let f=Math.max(2,Math.floor(this.width/480));for(let a=0;a<=this.width;a+=f){let c=d;if(c+=Math.sin(a*o.frequency+this.time*o.speed+h*.1)*o.amplitude,c+=Math.sin(a*o.frequency*1.5+this.time*o.speed*.7+s)*o.amplitude*.3,this.mouseActive){let v=a-this.mouseX,w=Math.abs(v)/this.width;c+=Math.sin(w*Math.PI)*(t>0?this.mouseY-this.height/2:0)*.1*(o.mouseInfluence||.45)}c+=l*Math.sin(a/this.width*Math.PI),e.lineTo(a,c)}e.lineTo(this.width,this.height),e.closePath();let m=o.color||"rgba(139, 114, 86, 0.25)";e.fillStyle=m.replace(/([\d.]+)\)$/,a=>`${parseFloat(a)*r})`),o.lineWidth!=null&&(e.lineWidth=o.lineWidth),e.fill()}}}drawParticles(e){for(let t of this.particles){t.pulse+=t.pulseSpeed;let s=t.opacity*(Math.sin(t.pulse)*.3+.7);if(this.mouseActive){let n=t.x-this.mouseX,h=t.y-this.mouseY,r=Math.sqrt(n*n+h*h);if(r<150&&r>.1){let d=(1-r/150)*2;t.x+=n/r*d,t.y+=h/r*d}}t.x+=t.speedX,t.y+=t.speedY,t.x<0&&(t.x=this.width),t.x>this.width&&(t.x=0),t.y<0&&(t.y=this.height),t.y>this.height&&(t.y=0);let o=e.createRadialGradient(t.x,t.y,0,t.x,t.y,t.size*2);o.addColorStop(0,t.colorPrefix+s+")"),o.addColorStop(1,t.colorPrefix+"0)"),e.beginPath(),e.fillStyle=o,e.arc(t.x,t.y,t.size*2,0,Math.PI*2),e.fill(),e.beginPath(),e.fillStyle=t.colorPrefix+s*.8+")",e.arc(t.x,t.y,t.size*.5,0,Math.PI*2),e.fill()}}drawMouseGlow(e){if(!this.mouseActive)return;let i=e.createRadialGradient(this.mouseX,this.mouseY,0,this.mouseX,this.mouseY,200);this.config.colors.mouseGlowStops.forEach(s=>i.addColorStop(s.offset,s.color)),e.beginPath(),e.fillStyle=i,e.arc(this.mouseX,this.mouseY,200,0,Math.PI*2),e.fill()}animate(){this.ctx&&(this.time+=1,this.mouseX+=(this.targetMouseX-this.mouseX)*.08,this.mouseY+=(this.targetMouseY-this.mouseY)*.08,this.ctx.clearRect(0,0,this.width,this.height),this.drawBackground(this.ctx),this.drawWaves(this.ctx),this.drawParticles(this.ctx),this.drawMouseGlow(this.ctx),this.isRunning&&requestAnimationFrame(()=>this.animate()))}start(){this.isRunning||(typeof window<"u"&&(window.addEventListener("mousemove",this._onMouseMove,{passive:!0}),window.addEventListener("touchmove",this._onTouchMove,{passive:!1}),window.addEventListener("touchend",this._onTouchEnd,{passive:!0}),window.addEventListener("mouseleave",this._onMouseLeave)),this.isRunning=!0,this.animate())}stop(){this.isRunning=!1,typeof window<"u"&&(window.removeEventListener("mousemove",this._onMouseMove),window.removeEventListener("touchmove",this._onTouchMove),window.removeEventListener("touchend",this._onTouchEnd),window.removeEventListener("mouseleave",this._onMouseLeave))}destroy(){this.stop(),typeof window<"u"&&window.removeEventListener("resize",this._onResize),this.canvas&&this.canvas.id==="wave-particles-canvas"&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas),this.canvas=null,this.ctx=null}},p=u;export{p as default};
1
+ var l=class{constructor(e={}){let{canvas:i,config:t}=e||{};this.canvas=null,this.ctx=null,this.mouseX=0,this.mouseY=0,this.targetMouseX=-1e3,this.targetMouseY=-1e3,this.mouseActive=!1,this.width=0,this.height=0,this.config=this._mergeDefaults(t||{}),this.time=0,this.isRunning=!1,this.particles=[],this._resizeTimeout=null;let s=typeof document<"u"&&i?typeof i=="string"?document.querySelector(i):i:null;if(s){this.canvas=s;let o=s.getBoundingClientRect();this.width=Math.round(o.width||window.innerWidth),this.height=Math.round(o.height||window.innerHeight)}else this._createAutoCanvas();try{if(!this.canvas)throw new Error("No canvas element available.");let o=this.canvas.getContext("2d");if(!o)throw new Error("Could not get 2D rendering context.");this.ctx=o}catch(o){console.error("[WaveParticles] Canvas error:",o);return}this._onMouseMove=this._onMouseMove.bind(this),this._onMouseLeave=this._onMouseLeave.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onResize=this._onResize.bind(this),typeof document<"u"&&(window.addEventListener("resize",this._onResize),this.resize()),this.initParticles(),this.start()}_mergeDefaults(e){let i={waves:[{amplitude:60,frequency:.003,speed:.006,yOffset:.55,color:"rgba(248, 225, 231, 0.25)",lineWidth:1.5,mouseInfluence:.45},{amplitude:50,frequency:.004,speed:.008,yOffset:.6,color:"rgba(212, 165, 165, 0.2)",lineWidth:1,mouseInfluence:.5},{amplitude:70,frequency:.0025,speed:.005,yOffset:.65,color:"rgba(255, 255, 255, 0.2)",lineWidth:1.5,mouseInfluence:.4},{amplitude:40,frequency:.0035,speed:.01,yOffset:.7,color:"rgba(201, 169, 110, 0.12)",lineWidth:1,mouseInfluence:.55}],particles:{countScale:8e3,maxCount:180},colors:{backgroundGradient:["#fdfcfb","#f7ede2","#e8d5d0"],particleColorPrefixes:["rgba(248, 225, 231,","rgba(212, 165, 165,","rgba(201, 169, 110,","rgba(255, 255, 255,","rgba(232, 213, 208,"],mouseGlowStops:[{offset:0,color:"rgba(255, 255, 255, 0.08)"},{offset:.5,color:"rgba(248, 225, 231, 0.04)"},{offset:1,color:"rgba(248, 225, 231, 0)"}]}},t={};for(let s in i)i.hasOwnProperty(s)&&(e&&e[s]?typeof i[s]=="object"&&!Array.isArray(i[s])&&typeof e[s]=="object"?t[s]=Object.assign({},i[s],e[s]):s==="waves"?t.waves=Array.isArray(e.waves)?[...e.waves]:JSON.parse(JSON.stringify(i.waves)):t[s]=e[s]:t[s]=JSON.parse(JSON.stringify(i[s])));return t}_createAutoCanvas(){if(typeof document>"u")return;let e=document.createElement("canvas");e.id="wave-particles-canvas",Object.assign(e.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",zIndex:"-1",pointerEvents:"none"});let i=document.body;i&&(i.insertBefore(e,i.firstChild),this.canvas=e,this.width=window.innerWidth,this.height=window.innerHeight)}_onResize(){this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this.resize()},250)}resize(){if(!this.canvas)return;let e=this.canvas.getBoundingClientRect(),i=window.devicePixelRatio||1,t=e.width||window.innerWidth,s=e.height||window.innerHeight;this.width=t,this.height=s,this.canvas.width=Math.round(t*i),this.canvas.height=Math.round(s*i),this.ctx||(this.ctx=this.canvas.getContext("2d")),this.ctx&&this.ctx.scale(i,i),this.isRunning&&this.initParticles()}initParticles(){let{countScale:e=8e3,maxCount:i=180}=this.config.particles,t=Math.min(Math.floor(this.width*this.height/(e>0?e:8e3)),i);this.particles=Array.from({length:t},()=>({x:Math.random()*this.width,y:Math.random()*this.height,size:Math.random()*4+1.5,speedX:(Math.random()-.5)*.4,speedY:(Math.random()-.5)*.4,opacity:Math.random()*.6+.3,pulse:Math.random()*Math.PI*2,pulseSpeed:Math.random()*.025+.01,colorPrefix:this.config.colors.particleColorPrefixes[Math.floor(Math.random()*this.config.colors.particleColorPrefixes.length)]}))}_onMouseMove(e){let i=this.canvas.getBoundingClientRect();i&&(this.targetMouseX=e.clientX-i.left,this.targetMouseY=e.clientY-i.top,this.mouseActive=!0)}_onMouseLeave(){this.mouseActive=!1}_onTouchMove(e){let i=e.touches[0],t=this.canvas.getBoundingClientRect();!i||!t||(this.targetMouseX=i.clientX-t.left,this.targetMouseY=i.clientY-t.top,this.mouseActive=!0)}_onTouchEnd(){this.mouseActive=!1}drawBackground(e){let i=this.config.colors.backgroundGradient,t=e.createRadialGradient(this.width/2,this.height/2,0,this.width/2,this.height/2,Math.max(this.width,this.height)*.8);i.forEach((s,o)=>t.addColorStop(o/(i.length-1||1),s)),e.fillStyle=t,e.fillRect(0,0,this.width,this.height)}drawWaves(e){let i=this.mouseActive?this.mouseX/this.width:-1,t=this.mouseActive?this.mouseY/this.height:-1;for(let s=0;s<this.config.waves.length;s++){let o=this.config.waves[s],r=Math.max(2,o.layers||2);for(let n=0;n<r;n++){let a=(1-n/r)*.5+.5;e.beginPath();let d=this.height*o.yOffset+n*3,u=this.mouseActive?(i-.5)*(o.mouseInfluence||.45)*150:0;e.moveTo(0,this.height);let f=Math.max(2,Math.floor(this.width/480));for(let h=0;h<=this.width;h+=f){let c=d;if(c+=Math.sin(h*o.frequency+this.time*o.speed+n*.1)*o.amplitude,c+=Math.sin(h*o.frequency*1.5+this.time*o.speed*.7+s)*o.amplitude*.3,this.mouseActive){let v=h-this.mouseX,w=Math.abs(v)/this.width;c+=Math.sin(w*Math.PI)*(t>0?this.mouseY-this.height/2:0)*.1*(o.mouseInfluence||.45)}c+=u*Math.sin(h/this.width*Math.PI),e.lineTo(h,c)}e.lineTo(this.width,this.height),e.closePath();let m=o.color||"rgba(139, 114, 86, 0.25)";e.fillStyle=m.replace(/([\d.]+)\)$/,h=>`${parseFloat(h)*a})`),o.lineWidth!=null&&(e.lineWidth=o.lineWidth),e.fill()}}}drawParticles(e){for(let t of this.particles){t.pulse+=t.pulseSpeed;let s=t.opacity*(Math.sin(t.pulse)*.3+.7);if(this.mouseActive){let r=t.x-this.mouseX,n=t.y-this.mouseY,a=Math.sqrt(r*r+n*n);if(a<150&&a>.1){let d=(1-a/150)*2;t.x+=r/a*d,t.y+=n/a*d}}t.x+=t.speedX,t.y+=t.speedY,t.x<0&&(t.x=this.width),t.x>this.width&&(t.x=0),t.y<0&&(t.y=this.height),t.y>this.height&&(t.y=0);let o=e.createRadialGradient(t.x,t.y,0,t.x,t.y,t.size*2);o.addColorStop(0,t.colorPrefix+s+")"),o.addColorStop(1,t.colorPrefix+"0)"),e.beginPath(),e.fillStyle=o,e.arc(t.x,t.y,t.size*2,0,Math.PI*2),e.fill(),e.beginPath(),e.fillStyle=t.colorPrefix+s*.8+")",e.arc(t.x,t.y,t.size*.5,0,Math.PI*2),e.fill()}}drawMouseGlow(e){if(!this.mouseActive)return;let i=e.createRadialGradient(this.mouseX,this.mouseY,0,this.mouseX,this.mouseY,200);this.config.colors.mouseGlowStops.forEach(s=>i.addColorStop(s.offset,s.color)),e.beginPath(),e.fillStyle=i,e.arc(this.mouseX,this.mouseY,200,0,Math.PI*2),e.fill()}animate(){this.ctx&&(this.time+=1,this.mouseX+=(this.targetMouseX-this.mouseX)*.08,this.mouseY+=(this.targetMouseY-this.mouseY)*.08,this.ctx.clearRect(0,0,this.width,this.height),this.drawBackground(this.ctx),this.drawWaves(this.ctx),this.drawParticles(this.ctx),this.drawMouseGlow(this.ctx),this.isRunning&&requestAnimationFrame(()=>this.animate()))}start(){this.isRunning||(typeof window<"u"&&(window.addEventListener("mousemove",this._onMouseMove,{passive:!0}),window.addEventListener("touchmove",this._onTouchMove,{passive:!1}),window.addEventListener("touchend",this._onTouchEnd,{passive:!0}),window.addEventListener("mouseleave",this._onMouseLeave)),this.isRunning=!0,this.animate())}stop(){this.isRunning=!1,typeof window<"u"&&(window.removeEventListener("mousemove",this._onMouseMove),window.removeEventListener("touchmove",this._onTouchMove),window.removeEventListener("touchend",this._onTouchEnd),window.removeEventListener("mouseleave",this._onMouseLeave))}destroy(){this.stop(),typeof window<"u"&&window.removeEventListener("resize",this._onResize),this.canvas&&this.canvas.id==="wave-particles-canvas"&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas),this.canvas=null,this.ctx=null}},p=l;export{p as default};
2
2
  //# sourceMappingURL=wave-particles.esm.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["/**\r\n * js-waves-particles\r\n * A canvas-based wave and particle animation library with mouse-reactive effects.\r\n * Developed by Luis 'PlatinumBlade' Moniz.\r\n */\r\n\r\nclass WaveParticles {\r\n /**\r\n * Initializes a new WaveParticles animation engine.\r\n *\r\n * @param {import('./index').WaveParticlesOptions} [options] - Configuration for the engine.\r\n * @param {HTMLCanvasElement|string} [options.canvas] - The target canvas element or a CSS selector (e.g., '#bg'). If omitted, a full-screen fixed canvas is automatically created.\r\n * @param {import('./index').WaveParticlesConfig} [options.config] - Visual parameters for waves, particles, and colors.\r\n */\r\n constructor(options = {}) {\r\n const {canvas: providedCanvasOrSelector, config} = options || {};\r\n\r\n // --- State ---\r\n this.canvas = null;\r\n this.ctx = null;\r\n this.mouseX = 0;\r\n this.mouseY = 0;\r\n this.targetMouseX = -1000;\r\n this.targetMouseY = -1000;\r\n this.mouseActive = false;\r\n this.width = 0;\r\n this.height = 0;\r\n this.config = this._mergeDefaults(config || {});\r\n this.time = 0;\r\n this.isRunning = false;\r\n this.particles = [];\r\n this._resizeTimeout = null;\r\n\r\n const resolvedCanvas = typeof document !== 'undefined' && providedCanvasOrSelector ? (() => {\r\n if (typeof providedCanvasOrSelector === 'string') {\r\n return /** @type {HTMLCanvasElement|null} */ (document.querySelector(providedCanvasOrSelector));\r\n }\r\n\r\n return /** @type {HTMLCanvasElement | null} */ (providedCanvasOrSelector);\r\n })() : null;\r\n\r\n if (resolvedCanvas) {\r\n this.canvas = resolvedCanvas;\r\n const rect = resolvedCanvas.getBoundingClientRect();\r\n this.width = Math.round(rect.width || window.innerWidth);\r\n this.height = Math.round(rect.height || window.innerHeight);\r\n } else {\r\n this._createAutoCanvas();\r\n }\r\n\r\n try {\r\n if (!this.canvas) {\r\n throw new Error('No canvas element available.');\r\n }\r\n\r\n const ctx = this.canvas.getContext('2d');\r\n\r\n if (!ctx) {\r\n throw new Error('Could not get 2D rendering context.');\r\n }\r\n\r\n this.ctx = ctx;\r\n } catch (e) {\r\n console.error('[WaveParticles] Canvas error:', e);\r\n return;\r\n }\r\n\r\n this._onMouseMove = this._onMouseMove.bind(this);\r\n this._onMouseLeave = this._onMouseLeave.bind(this);\r\n this._onTouchMove = this._onTouchMove.bind(this);\r\n this._onTouchEnd = this._onTouchEnd.bind(this);\r\n this._onResize = this._onResize.bind(this);\r\n\r\n if (typeof document !== 'undefined') {\r\n window.addEventListener('resize', this._onResize);\r\n this.resize(); // Initial size setup\r\n }\r\n\r\n this.initParticles();\r\n this.start();\r\n }\r\n\r\n /**\r\n * Internal method to merge user configuration with library defaults.\r\n * @private\r\n */\r\n _mergeDefaults(userConfig) {\r\n const defaults = {\r\n waves: [\r\n {\r\n amplitude: 60,\r\n frequency: 0.003,\r\n speed: 0.006,\r\n yOffset: 0.55,\r\n color: 'rgba(248, 225, 231, 0.25)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.45\r\n },\r\n {\r\n amplitude: 50,\r\n frequency: 0.004,\r\n speed: 0.008,\r\n yOffset: 0.60,\r\n color: 'rgba(212, 165, 165, 0.2)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.5\r\n },\r\n {\r\n amplitude: 70,\r\n frequency: 0.0025,\r\n speed: 0.005,\r\n yOffset: 0.65,\r\n color: 'rgba(255, 255, 255, 0.2)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.4\r\n },\r\n {\r\n amplitude: 40,\r\n frequency: 0.0035,\r\n speed: 0.010,\r\n yOffset: 0.70,\r\n color: 'rgba(201, 169, 110, 0.12)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.55\r\n }\r\n ],\r\n particles: {countScale: 8000, maxCount: 180},\r\n colors: {\r\n backgroundGradient: ['#fdfcfb', '#f7ede2', '#e8d5d0'],\r\n particleColorPrefixes: [\r\n 'rgba(248, 225, 231,',\r\n 'rgba(212, 165, 165,',\r\n 'rgba(201, 169, 110,',\r\n 'rgba(255, 255, 255,',\r\n 'rgba(232, 213, 208,'\r\n ],\r\n mouseGlowStops: [\r\n {offset: 0, color: 'rgba(255, 255, 255, 0.08)'},\r\n {offset: 0.5, color: 'rgba(248, 225, 231, 0.04)'},\r\n {offset: 1, color: 'rgba(248, 225, 231, 0)'}\r\n ]\r\n }\r\n };\r\n\r\n const result = {};\r\n\r\n for (const key in defaults) {\r\n if (!defaults.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n if (!(userConfig && userConfig[key])) {\r\n result[key] = JSON.parse(JSON.stringify(defaults[key]));\r\n } else if (typeof defaults[key] === 'object' && !Array.isArray(defaults[key]) && typeof userConfig[key] === 'object') {\r\n result[key] = Object.assign({}, defaults[key], userConfig[key]);\r\n } else if (key === 'waves') {\r\n result.waves = Array.isArray(userConfig.waves) ? [...userConfig.waves] : JSON.parse(JSON.stringify(defaults.waves));\r\n } else {\r\n result[key] = userConfig[key];\r\n }\r\n }\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Automatically creates and injects a canvas element into the DOM if none was provided.\r\n * @private\r\n */\r\n _createAutoCanvas() {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const el = document.createElement('canvas');\r\n\r\n el.id = 'wave-particles-canvas';\r\n\r\n Object.assign(el.style, {\r\n position: 'fixed',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n zIndex: '-1',\r\n pointerEvents: 'none'\r\n });\r\n\r\n const body = document.body;\r\n\r\n if (!body) {\r\n return;\r\n }\r\n\r\n body.insertBefore(el, body.firstChild);\r\n this.canvas = el;\r\n this.width = window.innerWidth;\r\n this.height = window.innerHeight;\r\n }\r\n\r\n /**\r\n * Event handler for window resize events, including debouncing to prevent performance issues.\r\n * @private\r\n */\r\n _onResize() {\r\n if (this._resizeTimeout) clearTimeout(this._resizeTimeout);\r\n // Debounce resize to prevent flashing and high CPU usage\r\n this._resizeTimeout = setTimeout(() => {\r\n this.resize();\r\n }, 250);\r\n }\r\n\r\n /**\r\n * Recalculates canvas dimensions based on its display size and Device Pixel Ratio.\r\n * Re-initializes particles to match the new surface area.\r\n */\r\n resize() {\r\n if (!this.canvas) {\r\n return;\r\n }\r\n\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n let w, h;\r\n\r\n const attrW = parseInt(this.canvas.getAttribute('width'), 10);\r\n const attrH = parseInt(this.canvas.getAttribute('height'), 10);\r\n\r\n if (attrW && attrH) {\r\n w = Math.round(rect.width || attrW);\r\n h = Math.round(rect.height || attrH);\r\n } else {\r\n w = window.innerWidth;\r\n h = window.innerHeight;\r\n\r\n if (!this.canvas.parentNode && document.body) {\r\n document.body.insertBefore(this.canvas, document.body.firstChild);\r\n }\r\n }\r\n \r\n this.width = w;\r\n this.height = h;\r\n\r\n const dpr = window.devicePixelRatio || 1;\r\n\r\n this.canvas.width = Math.round(w * dpr);\r\n this.canvas.height = Math.round(h * dpr);\r\n\r\n if (this.ctx && this.isRunning) {\r\n this.initParticles();\r\n }\r\n }\r\n\r\n /**\r\n * Generates a new set of particles based on the current canvas area and configuration.\r\n */\r\n initParticles() {\r\n const {countScale = 8000, maxCount = 180} = this.config.particles;\r\n\r\n const particleCount = Math.min(Math.floor((this.width * this.height) / (countScale > 0 ? countScale : 8000)), maxCount);\r\n\r\n this.particles = Array.from({length: particleCount}, () => ({\r\n x: Math.random() * this.width,\r\n y: Math.random() * this.height,\r\n size: Math.random() * 4 + 1.5,\r\n speedX: (Math.random() - 0.5) * 0.4,\r\n speedY: (Math.random() - 0.5) * 0.4,\r\n opacity: Math.random() * 0.6 + 0.3,\r\n pulse: Math.random() * Math.PI * 2,\r\n pulseSpeed: Math.random() * 0.025 + 0.01,\r\n colorPrefix: this.config.colors.particleColorPrefixes[Math.floor(Math.random() * this.config.colors.particleColorPrefixes.length)]\r\n }));\r\n }\r\n\r\n _onMouseMove(e) {\r\n const rect = this.canvas.getBoundingClientRect();\r\n \r\n if (!rect) {\r\n return;\r\n }\r\n\r\n // Calculate position relative to the canvas in CSS pixels\r\n this.targetMouseX = e.clientX - rect.left;\r\n this.targetMouseY = e.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onMouseLeave() {\r\n this.mouseActive = false;\r\n }\r\n\r\n _onTouchMove(e) {\r\n const touch = e.touches[0];\r\n const rect = this.canvas.getBoundingClientRect();\r\n \r\n if (!touch || !rect) {\r\n return;\r\n }\r\n\r\n this.targetMouseX = touch.clientX - rect.left;\r\n this.targetMouseY = touch.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onTouchEnd() {\r\n this.mouseActive = false;\r\n }\r\n\r\n /**\r\n * Renders the radial gradient background across the entire canvas.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawBackground(ctx) {\r\n const colors = this.config.colors.backgroundGradient;\r\n \r\n const gradient = ctx.createRadialGradient(this.width / 2, this.height / 2, 0, this.width / 2, this.height / 2, Math.max(this.width, this.height) * 0.8);\r\n \r\n colors.forEach((c, i) => gradient.addColorStop(i / (colors.length - 1 || 1), c));\r\n \r\n ctx.fillStyle = gradient;\r\n \r\n ctx.fillRect(0, 0, this.width, this.height);\r\n }\r\n\r\n /**\r\n * Renders all wave layers, accounting for mouse interaction and layer offsets.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawWaves(ctx) {\r\n const mouseNormX = this.mouseActive ? this.mouseX / this.width : -1;\r\n const mouseNormY = this.mouseActive ? this.mouseY / this.height : -1;\r\n\r\n for (let wi = 0; wi < this.config.waves.length; wi++) {\r\n const wave = this.config.waves[wi];\r\n const numLayers = Math.max(2, wave.layers || 2);\r\n\r\n for (let layer = 0; layer < numLayers; layer++) {\r\n const layerOpacity = (1 - layer / numLayers) * 0.5 + 0.5;\r\n \r\n ctx.beginPath();\r\n \r\n const baseY = this.height * wave.yOffset + layer * 3;\r\n \r\n const mouseEffect = this.mouseActive ? (mouseNormX - 0.5) * (wave.mouseInfluence || 0.45) * 150 : 0;\r\n \r\n ctx.moveTo(0, this.height);\r\n\r\n const step = Math.max(2, Math.floor(this.width / 480));\r\n \r\n for (let x = 0; x <= this.width; x += step) {\r\n let y = baseY;\r\n \r\n y += Math.sin(x * wave.frequency + this.time * wave.speed + layer * 0.1) * wave.amplitude;\r\n y += Math.sin(x * wave.frequency * 1.5 + this.time * wave.speed * 0.7 + wi) * wave.amplitude * 0.3;\r\n \r\n if (this.mouseActive) {\r\n const dx = x - this.mouseX;\r\n const dist = Math.abs(dx) / this.width;\r\n y += Math.sin(dist * Math.PI) * (mouseNormY > 0 ? (this.mouseY - this.height / 2) : 0) * 0.1 * (wave.mouseInfluence || 0.45);\r\n }\r\n \r\n y += mouseEffect * Math.sin((x / this.width) * Math.PI);\r\n \r\n ctx.lineTo(x, y);\r\n }\r\n \r\n ctx.lineTo(this.width, this.height);\r\n \r\n ctx.closePath();\r\n \r\n const baseColor = wave.color || 'rgba(139, 114, 86, 0.25)';\r\n \r\n ctx.fillStyle = baseColor.replace(/([\\d.]+)\\)$/, (m) => `${parseFloat(m) * layerOpacity})`);\r\n \r\n if (wave.lineWidth != null) {\r\n ctx.lineWidth = wave.lineWidth;\r\n }\r\n \r\n ctx.fill();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates and renders the particle system, including movement and mouse repulsion logic.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawParticles(ctx) {\r\n const maxDist = 150;\r\n \r\n for (const p of this.particles) {\r\n p.pulse += p.pulseSpeed;\r\n \r\n const currentOpacity = p.opacity * (Math.sin(p.pulse) * 0.3 + 0.7);\r\n \r\n if (this.mouseActive) {\r\n const dx = p.x - this.mouseX, dy = p.y - this.mouseY, dist = Math.sqrt(dx * dx + dy * dy);\r\n \r\n if (dist < maxDist && dist > 0.1) {\r\n const force = (1 - dist / maxDist) * 2;\r\n p.x += (dx / dist) * force;\r\n p.y += (dy / dist) * force;\r\n }\r\n }\r\n \r\n p.x += p.speedX;\r\n p.y += p.speedY;\r\n \r\n if (p.x < 0) {\r\n p.x = this.width;\r\n }\r\n \r\n if (p.x > this.width) {\r\n p.x = 0;\r\n }\r\n \r\n if (p.y < 0) {\r\n p.y = this.height;\r\n }\r\n \r\n if (p.y > this.height) {\r\n p.y = 0;\r\n }\r\n\r\n const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 2);\r\n \r\n grad.addColorStop(0, p.colorPrefix + currentOpacity + ')');\r\n \r\n grad.addColorStop(1, p.colorPrefix + '0)');\r\n \r\n ctx.beginPath();\r\n \r\n ctx.fillStyle = grad;\r\n \r\n ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2);\r\n \r\n ctx.fill();\r\n \r\n ctx.beginPath();\r\n \r\n ctx.fillStyle = p.colorPrefix + (currentOpacity * 0.8) + ')';\r\n \r\n ctx.arc(p.x, p.y, p.size * 0.5, 0, Math.PI * 2);\r\n \r\n ctx.fill();\r\n }\r\n }\r\n\r\n /**\r\n * Renders a soft glow effect centered at the current mouse position.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawMouseGlow(ctx) {\r\n if (!this.mouseActive) {\r\n return;\r\n }\r\n \r\n const gradient = ctx.createRadialGradient(this.mouseX, this.mouseY, 0, this.mouseX, this.mouseY, 200);\r\n \r\n const stops = this.config.colors.mouseGlowStops;\r\n \r\n stops.forEach((s) => gradient.addColorStop(s.offset, s.color));\r\n \r\n ctx.beginPath();\r\n \r\n ctx.fillStyle = gradient;\r\n \r\n ctx.arc(this.mouseX, this.mouseY, 200, 0, Math.PI * 2);\r\n \r\n ctx.fill();\r\n }\r\n\r\n /**\r\n * The main animation loop. Updates state and draws the next frame.\r\n */\r\n animate() {\r\n if (!this.ctx) {\r\n return;\r\n }\r\n \r\n this.time += 1;\r\n \r\n this.mouseX += (this.targetMouseX - this.mouseX) * 0.08;\r\n this.mouseY += (this.targetMouseY - this.mouseY) * 0.08;\r\n \r\n this.ctx.clearRect(0, 0, this.width, this.height);\r\n \r\n this.drawBackground(this.ctx);\r\n this.drawWaves(this.ctx);\r\n this.drawParticles(this.ctx);\r\n this.drawMouseGlow(this.ctx);\r\n \r\n if (this.isRunning) {\r\n requestAnimationFrame(() => this.animate());\r\n }\r\n }\r\n\r\n /**\r\n * Starts or resumes the animation loop and attaches interaction listeners.\r\n */\r\n start() {\r\n if (this.isRunning) {\r\n return;\r\n }\r\n \r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('mousemove', this._onMouseMove, {passive: true});\r\n window.addEventListener('touchmove', this._onTouchMove, {passive: false});\r\n window.addEventListener('touchend', this._onTouchEnd, {passive: true});\r\n window.addEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n \r\n this.isRunning = true;\r\n \r\n this.animate();\r\n }\r\n\r\n /**\r\n * Pauses the animation loop and detaches interaction listeners to save resources.\r\n */\r\n stop() {\r\n this.isRunning = false;\r\n \r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('mousemove', this._onMouseMove);\r\n window.removeEventListener('touchmove', this._onTouchMove);\r\n window.removeEventListener('touchend', this._onTouchEnd);\r\n window.removeEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n }\r\n\r\n /**\r\n * Stops the animation, removes event listeners, and cleans up any auto-injected DOM elements.\r\n */\r\n destroy() {\r\n this.stop();\r\n \r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('resize', this._onResize);\r\n }\r\n \r\n if (this.canvas && this.canvas.id === 'wave-particles-canvas' && this.canvas.parentNode) {\r\n this.canvas.parentNode.removeChild(this.canvas);\r\n }\r\n \r\n this.canvas = null;\r\n this.ctx = null;\r\n }\r\n}\r\n\r\nexport default WaveParticles;\r\n"],
5
- "mappings": "AAMA,IAAMA,EAAN,KAAoB,CAQhB,YAAYC,EAAU,CAAC,EAAG,CACtB,GAAM,CAAC,OAAQC,EAA0B,OAAAC,CAAM,EAAIF,GAAW,CAAC,EAG/D,KAAK,OAAS,KACd,KAAK,IAAM,KACX,KAAK,OAAS,EACd,KAAK,OAAS,EACd,KAAK,aAAe,KACpB,KAAK,aAAe,KACpB,KAAK,YAAc,GACnB,KAAK,MAAQ,EACb,KAAK,OAAS,EACd,KAAK,OAAS,KAAK,eAAeE,GAAU,CAAC,CAAC,EAC9C,KAAK,KAAO,EACZ,KAAK,UAAY,GACjB,KAAK,UAAY,CAAC,EAClB,KAAK,eAAiB,KAEtB,IAAMC,EAAiB,OAAO,SAAa,KAAeF,EAClD,OAAOA,GAA6B,SACU,SAAS,cAAcA,CAAwB,EAGjDA,EAC7C,KAEP,GAAIE,EAAgB,CAChB,KAAK,OAASA,EACd,IAAMC,EAAOD,EAAe,sBAAsB,EAClD,KAAK,MAAQ,KAAK,MAAMC,EAAK,OAAS,OAAO,UAAU,EACvD,KAAK,OAAS,KAAK,MAAMA,EAAK,QAAU,OAAO,WAAW,CAC9D,MACI,KAAK,kBAAkB,EAG3B,GAAI,CACA,GAAI,CAAC,KAAK,OACN,MAAM,IAAI,MAAM,8BAA8B,EAGlD,IAAMC,EAAM,KAAK,OAAO,WAAW,IAAI,EAEvC,GAAI,CAACA,EACD,MAAM,IAAI,MAAM,qCAAqC,EAGzD,KAAK,IAAMA,CACf,OAASC,EAAG,CACR,QAAQ,MAAM,gCAAiCA,CAAC,EAChD,MACJ,CAEA,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,cAAgB,KAAK,cAAc,KAAK,IAAI,EACjD,KAAK,aAAe,KAAK,aAAa,KAAK,IAAI,EAC/C,KAAK,YAAc,KAAK,YAAY,KAAK,IAAI,EAC7C,KAAK,UAAY,KAAK,UAAU,KAAK,IAAI,EAErC,OAAO,SAAa,MACpB,OAAO,iBAAiB,SAAU,KAAK,SAAS,EAChD,KAAK,OAAO,GAGhB,KAAK,cAAc,EACnB,KAAK,MAAM,CACf,CAMA,eAAeC,EAAY,CACvB,IAAMC,EAAW,CACb,MAAO,CACH,CACI,UAAW,GACX,UAAW,KACX,MAAO,KACP,QAAS,IACT,MAAO,4BACP,UAAW,IACX,eAAgB,GACpB,EACA,CACI,UAAW,GACX,UAAW,KACX,MAAO,KACP,QAAS,GACT,MAAO,2BACP,UAAW,EACX,eAAgB,EACpB,EACA,CACI,UAAW,GACX,UAAW,MACX,MAAO,KACP,QAAS,IACT,MAAO,2BACP,UAAW,IACX,eAAgB,EACpB,EACA,CACI,UAAW,GACX,UAAW,MACX,MAAO,IACP,QAAS,GACT,MAAO,4BACP,UAAW,EACX,eAAgB,GACpB,CACJ,EACA,UAAW,CAAC,WAAY,IAAM,SAAU,GAAG,EAC3C,OAAQ,CACJ,mBAAoB,CAAC,UAAW,UAAW,SAAS,EACpD,sBAAuB,CACnB,sBACA,sBACA,sBACA,sBACA,qBACJ,EACA,eAAgB,CACZ,CAAC,OAAQ,EAAG,MAAO,2BAA2B,EAC9C,CAAC,OAAQ,GAAK,MAAO,2BAA2B,EAChD,CAAC,OAAQ,EAAG,MAAO,wBAAwB,CAC/C,CACJ,CACJ,EAEMC,EAAS,CAAC,EAEhB,QAAWC,KAAOF,EACTA,EAAS,eAAeE,CAAG,IAI1BH,GAAcA,EAAWG,CAAG,EAEvB,OAAOF,EAASE,CAAG,GAAM,UAAY,CAAC,MAAM,QAAQF,EAASE,CAAG,CAAC,GAAK,OAAOH,EAAWG,CAAG,GAAM,SACxGD,EAAOC,CAAG,EAAI,OAAO,OAAO,CAAC,EAAGF,EAASE,CAAG,EAAGH,EAAWG,CAAG,CAAC,EACvDA,IAAQ,QACfD,EAAO,MAAQ,MAAM,QAAQF,EAAW,KAAK,EAAI,CAAC,GAAGA,EAAW,KAAK,EAAI,KAAK,MAAM,KAAK,UAAUC,EAAS,KAAK,CAAC,EAElHC,EAAOC,CAAG,EAAIH,EAAWG,CAAG,EAN5BD,EAAOC,CAAG,EAAI,KAAK,MAAM,KAAK,UAAUF,EAASE,CAAG,CAAC,CAAC,GAU9D,OAAOD,CACX,CAMA,mBAAoB,CAChB,GAAI,OAAO,SAAa,IACpB,OAGJ,IAAME,EAAK,SAAS,cAAc,QAAQ,EAE1CA,EAAG,GAAK,wBAER,OAAO,OAAOA,EAAG,MAAO,CACpB,SAAU,QACV,IAAK,IACL,KAAM,IACN,MAAO,OACP,OAAQ,OACR,OAAQ,KACR,cAAe,MACnB,CAAC,EAED,IAAMC,EAAO,SAAS,KAEjBA,IAILA,EAAK,aAAaD,EAAIC,EAAK,UAAU,EACrC,KAAK,OAASD,EACd,KAAK,MAAQ,OAAO,WACpB,KAAK,OAAS,OAAO,YACzB,CAMA,WAAY,CACJ,KAAK,gBAAgB,aAAa,KAAK,cAAc,EAEzD,KAAK,eAAiB,WAAW,IAAM,CACnC,KAAK,OAAO,CAChB,EAAG,GAAG,CACV,CAMA,QAAS,CACL,GAAI,CAAC,KAAK,OACN,OAGJ,IAAMP,EAAO,KAAK,OAAO,sBAAsB,EAE3CS,EAAGC,EAEDC,EAAQ,SAAS,KAAK,OAAO,aAAa,OAAO,EAAG,EAAE,EACtDC,EAAQ,SAAS,KAAK,OAAO,aAAa,QAAQ,EAAG,EAAE,EAEzDD,GAASC,GACTH,EAAI,KAAK,MAAMT,EAAK,OAASW,CAAK,EAClCD,EAAI,KAAK,MAAMV,EAAK,QAAUY,CAAK,IAEnCH,EAAI,OAAO,WACXC,EAAI,OAAO,YAEP,CAAC,KAAK,OAAO,YAAc,SAAS,MACpC,SAAS,KAAK,aAAa,KAAK,OAAQ,SAAS,KAAK,UAAU,GAIxE,KAAK,MAAQD,EACb,KAAK,OAASC,EAEd,IAAMG,EAAM,OAAO,kBAAoB,EAEvC,KAAK,OAAO,MAAQ,KAAK,MAAMJ,EAAII,CAAG,EACtC,KAAK,OAAO,OAAS,KAAK,MAAMH,EAAIG,CAAG,EAEnC,KAAK,KAAO,KAAK,WACjB,KAAK,cAAc,CAE3B,CAKA,eAAgB,CACZ,GAAM,CAAC,WAAAC,EAAa,IAAM,SAAAC,EAAW,GAAG,EAAI,KAAK,OAAO,UAElDC,EAAgB,KAAK,IAAI,KAAK,MAAO,KAAK,MAAQ,KAAK,QAAWF,EAAa,EAAIA,EAAa,IAAK,EAAGC,CAAQ,EAEtH,KAAK,UAAY,MAAM,KAAK,CAAC,OAAQC,CAAa,EAAG,KAAO,CACxD,EAAG,KAAK,OAAO,EAAI,KAAK,MACxB,EAAG,KAAK,OAAO,EAAI,KAAK,OACxB,KAAM,KAAK,OAAO,EAAI,EAAI,IAC1B,QAAS,KAAK,OAAO,EAAI,IAAO,GAChC,QAAS,KAAK,OAAO,EAAI,IAAO,GAChC,QAAS,KAAK,OAAO,EAAI,GAAM,GAC/B,MAAO,KAAK,OAAO,EAAI,KAAK,GAAK,EACjC,WAAY,KAAK,OAAO,EAAI,KAAQ,IACpC,YAAa,KAAK,OAAO,OAAO,sBAAsB,KAAK,MAAM,KAAK,OAAO,EAAI,KAAK,OAAO,OAAO,sBAAsB,MAAM,CAAC,CACrI,EAAE,CACN,CAEA,aAAa,EAAG,CACZ,IAAMhB,EAAO,KAAK,OAAO,sBAAsB,EAE1CA,IAKL,KAAK,aAAe,EAAE,QAAUA,EAAK,KACrC,KAAK,aAAe,EAAE,QAAUA,EAAK,IACrC,KAAK,YAAc,GACvB,CAEA,eAAgB,CACZ,KAAK,YAAc,EACvB,CAEA,aAAa,EAAG,CACZ,IAAMiB,EAAQ,EAAE,QAAQ,CAAC,EACnBjB,EAAO,KAAK,OAAO,sBAAsB,EAE3C,CAACiB,GAAS,CAACjB,IAIf,KAAK,aAAeiB,EAAM,QAAUjB,EAAK,KACzC,KAAK,aAAeiB,EAAM,QAAUjB,EAAK,IACzC,KAAK,YAAc,GACvB,CAEA,aAAc,CACV,KAAK,YAAc,EACvB,CAMA,eAAeC,EAAK,CAChB,IAAMiB,EAAS,KAAK,OAAO,OAAO,mBAE5BC,EAAWlB,EAAI,qBAAqB,KAAK,MAAQ,EAAG,KAAK,OAAS,EAAG,EAAG,KAAK,MAAQ,EAAG,KAAK,OAAS,EAAG,KAAK,IAAI,KAAK,MAAO,KAAK,MAAM,EAAI,EAAG,EAEtJiB,EAAO,QAAQ,CAACE,EAAGC,IAAMF,EAAS,aAAaE,GAAKH,EAAO,OAAS,GAAK,GAAIE,CAAC,CAAC,EAE/EnB,EAAI,UAAYkB,EAEhBlB,EAAI,SAAS,EAAG,EAAG,KAAK,MAAO,KAAK,MAAM,CAC9C,CAMA,UAAUA,EAAK,CACX,IAAMqB,EAAa,KAAK,YAAc,KAAK,OAAS,KAAK,MAAQ,GAC3DC,EAAa,KAAK,YAAc,KAAK,OAAS,KAAK,OAAS,GAElE,QAASC,EAAK,EAAGA,EAAK,KAAK,OAAO,MAAM,OAAQA,IAAM,CAClD,IAAMC,EAAO,KAAK,OAAO,MAAMD,CAAE,EAC3BE,EAAY,KAAK,IAAI,EAAGD,EAAK,QAAU,CAAC,EAE9C,QAASE,EAAQ,EAAGA,EAAQD,EAAWC,IAAS,CAC5C,IAAMC,GAAgB,EAAID,EAAQD,GAAa,GAAM,GAErDzB,EAAI,UAAU,EAEd,IAAM4B,EAAQ,KAAK,OAASJ,EAAK,QAAUE,EAAQ,EAE7CG,EAAc,KAAK,aAAeR,EAAa,KAAQG,EAAK,gBAAkB,KAAQ,IAAM,EAElGxB,EAAI,OAAO,EAAG,KAAK,MAAM,EAEzB,IAAM8B,EAAO,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,MAAQ,GAAG,CAAC,EAErD,QAASC,EAAI,EAAGA,GAAK,KAAK,MAAOA,GAAKD,EAAM,CACxC,IAAIE,EAAIJ,EAKR,GAHAI,GAAK,KAAK,IAAID,EAAIP,EAAK,UAAY,KAAK,KAAOA,EAAK,MAAQE,EAAQ,EAAG,EAAIF,EAAK,UAChFQ,GAAK,KAAK,IAAID,EAAIP,EAAK,UAAY,IAAM,KAAK,KAAOA,EAAK,MAAQ,GAAMD,CAAE,EAAIC,EAAK,UAAY,GAE3F,KAAK,YAAa,CAClB,IAAMS,EAAKF,EAAI,KAAK,OACdG,EAAO,KAAK,IAAID,CAAE,EAAI,KAAK,MACjCD,GAAK,KAAK,IAAIE,EAAO,KAAK,EAAE,GAAKZ,EAAa,EAAK,KAAK,OAAS,KAAK,OAAS,EAAK,GAAK,IAAOE,EAAK,gBAAkB,IAC3H,CAEAQ,GAAKH,EAAc,KAAK,IAAKE,EAAI,KAAK,MAAS,KAAK,EAAE,EAEtD/B,EAAI,OAAO+B,EAAGC,CAAC,CACnB,CAEAhC,EAAI,OAAO,KAAK,MAAO,KAAK,MAAM,EAElCA,EAAI,UAAU,EAEd,IAAMmC,EAAYX,EAAK,OAAS,2BAEhCxB,EAAI,UAAYmC,EAAU,QAAQ,cAAgBC,GAAM,GAAG,WAAWA,CAAC,EAAIT,CAAY,GAAG,EAEtFH,EAAK,WAAa,OAClBxB,EAAI,UAAYwB,EAAK,WAGzBxB,EAAI,KAAK,CACb,CACJ,CACJ,CAMA,cAAcA,EAAK,CAGf,QAAWqC,KAAK,KAAK,UAAW,CAC5BA,EAAE,OAASA,EAAE,WAEb,IAAMC,EAAiBD,EAAE,SAAW,KAAK,IAAIA,EAAE,KAAK,EAAI,GAAM,IAE9D,GAAI,KAAK,YAAa,CAClB,IAAMJ,EAAKI,EAAE,EAAI,KAAK,OAAQE,EAAKF,EAAE,EAAI,KAAK,OAAQH,EAAO,KAAK,KAAKD,EAAKA,EAAKM,EAAKA,CAAE,EAExF,GAAIL,EAAO,KAAWA,EAAO,GAAK,CAC9B,IAAMM,GAAS,EAAIN,EAAO,KAAW,EACrCG,EAAE,GAAMJ,EAAKC,EAAQM,EACrBH,EAAE,GAAME,EAAKL,EAAQM,CACzB,CACJ,CAEAH,EAAE,GAAKA,EAAE,OACTA,EAAE,GAAKA,EAAE,OAELA,EAAE,EAAI,IACNA,EAAE,EAAI,KAAK,OAGXA,EAAE,EAAI,KAAK,QACXA,EAAE,EAAI,GAGNA,EAAE,EAAI,IACNA,EAAE,EAAI,KAAK,QAGXA,EAAE,EAAI,KAAK,SACXA,EAAE,EAAI,GAGV,IAAMI,EAAOzC,EAAI,qBAAqBqC,EAAE,EAAGA,EAAE,EAAG,EAAGA,EAAE,EAAGA,EAAE,EAAGA,EAAE,KAAO,CAAC,EAEvEI,EAAK,aAAa,EAAGJ,EAAE,YAAcC,EAAiB,GAAG,EAEzDG,EAAK,aAAa,EAAGJ,EAAE,YAAc,IAAI,EAEzCrC,EAAI,UAAU,EAEdA,EAAI,UAAYyC,EAEhBzC,EAAI,IAAIqC,EAAE,EAAGA,EAAE,EAAGA,EAAE,KAAO,EAAG,EAAG,KAAK,GAAK,CAAC,EAE5CrC,EAAI,KAAK,EAETA,EAAI,UAAU,EAEdA,EAAI,UAAYqC,EAAE,YAAeC,EAAiB,GAAO,IAEzDtC,EAAI,IAAIqC,EAAE,EAAGA,EAAE,EAAGA,EAAE,KAAO,GAAK,EAAG,KAAK,GAAK,CAAC,EAE9CrC,EAAI,KAAK,CACb,CACJ,CAMA,cAAcA,EAAK,CACf,GAAI,CAAC,KAAK,YACN,OAGJ,IAAMkB,EAAWlB,EAAI,qBAAqB,KAAK,OAAQ,KAAK,OAAQ,EAAG,KAAK,OAAQ,KAAK,OAAQ,GAAG,EAEtF,KAAK,OAAO,OAAO,eAE3B,QAAS,GAAMkB,EAAS,aAAa,EAAE,OAAQ,EAAE,KAAK,CAAC,EAE7DlB,EAAI,UAAU,EAEdA,EAAI,UAAYkB,EAEhBlB,EAAI,IAAI,KAAK,OAAQ,KAAK,OAAQ,IAAK,EAAG,KAAK,GAAK,CAAC,EAErDA,EAAI,KAAK,CACb,CAKA,SAAU,CACD,KAAK,MAIV,KAAK,MAAQ,EAEb,KAAK,SAAW,KAAK,aAAe,KAAK,QAAU,IACnD,KAAK,SAAW,KAAK,aAAe,KAAK,QAAU,IAEnD,KAAK,IAAI,UAAU,EAAG,EAAG,KAAK,MAAO,KAAK,MAAM,EAEhD,KAAK,eAAe,KAAK,GAAG,EAC5B,KAAK,UAAU,KAAK,GAAG,EACvB,KAAK,cAAc,KAAK,GAAG,EAC3B,KAAK,cAAc,KAAK,GAAG,EAEvB,KAAK,WACL,sBAAsB,IAAM,KAAK,QAAQ,CAAC,EAElD,CAKA,OAAQ,CACA,KAAK,YAIL,OAAO,OAAW,MAClB,OAAO,iBAAiB,YAAa,KAAK,aAAc,CAAC,QAAS,EAAI,CAAC,EACvE,OAAO,iBAAiB,YAAa,KAAK,aAAc,CAAC,QAAS,EAAK,CAAC,EACxE,OAAO,iBAAiB,WAAY,KAAK,YAAa,CAAC,QAAS,EAAI,CAAC,EACrE,OAAO,iBAAiB,aAAc,KAAK,aAAa,GAG5D,KAAK,UAAY,GAEjB,KAAK,QAAQ,EACjB,CAKA,MAAO,CACH,KAAK,UAAY,GAEb,OAAO,OAAW,MAClB,OAAO,oBAAoB,YAAa,KAAK,YAAY,EACzD,OAAO,oBAAoB,YAAa,KAAK,YAAY,EACzD,OAAO,oBAAoB,WAAY,KAAK,WAAW,EACvD,OAAO,oBAAoB,aAAc,KAAK,aAAa,EAEnE,CAKA,SAAU,CACN,KAAK,KAAK,EAEN,OAAO,OAAW,KAClB,OAAO,oBAAoB,SAAU,KAAK,SAAS,EAGnD,KAAK,QAAU,KAAK,OAAO,KAAO,yBAA2B,KAAK,OAAO,YACzE,KAAK,OAAO,WAAW,YAAY,KAAK,MAAM,EAGlD,KAAK,OAAS,KACd,KAAK,IAAM,IACf,CACJ,EAEO0C,EAAQhD",
6
- "names": ["WaveParticles", "options", "providedCanvasOrSelector", "config", "resolvedCanvas", "rect", "ctx", "e", "userConfig", "defaults", "result", "key", "el", "body", "w", "h", "attrW", "attrH", "dpr", "countScale", "maxCount", "particleCount", "touch", "colors", "gradient", "c", "i", "mouseNormX", "mouseNormY", "wi", "wave", "numLayers", "layer", "layerOpacity", "baseY", "mouseEffect", "step", "x", "y", "dx", "dist", "baseColor", "m", "p", "currentOpacity", "dy", "force", "grad", "src_default"]
4
+ "sourcesContent": ["/**\r\n * js-waves-particles\r\n * A canvas-based wave and particle animation library with mouse-reactive effects.\r\n * Developed by Luis 'PlatinumBlade' Moniz.\r\n */\r\n\r\nclass WaveParticles {\r\n /**\r\n * Initializes a new WaveParticles animation engine.\r\n *\r\n * @param {import('./index').WaveParticlesOptions} [options] - Configuration for the engine.\r\n * @param {HTMLCanvasElement|string} [options.canvas] - The target canvas element or a CSS selector (e.g., '#bg'). If omitted, a full-screen fixed canvas is automatically created.\r\n * @param {import('./index').WaveParticlesConfig} [options.config] - Visual parameters for waves, particles, and colors.\r\n */\r\n constructor(options = {}) {\r\n const { canvas: providedCanvasOrSelector, config } = options || {};\r\n\r\n // --- State ---\r\n this.canvas = null;\r\n this.ctx = null;\r\n this.mouseX = 0;\r\n this.mouseY = 0;\r\n this.targetMouseX = -1000;\r\n this.targetMouseY = -1000;\r\n this.mouseActive = false;\r\n this.width = 0;\r\n this.height = 0;\r\n this.config = this._mergeDefaults(config || {});\r\n this.time = 0;\r\n this.isRunning = false;\r\n this.particles = [];\r\n this._resizeTimeout = null;\r\n\r\n const resolvedCanvas = typeof document !== 'undefined' && providedCanvasOrSelector ? (() => {\r\n if (typeof providedCanvasOrSelector === 'string') {\r\n return /** @type {HTMLCanvasElement|null} */ (document.querySelector(providedCanvasOrSelector));\r\n }\r\n\r\n return /** @type {HTMLCanvasElement | null} */ (providedCanvasOrSelector);\r\n })() : null;\r\n\r\n if (resolvedCanvas) {\r\n this.canvas = resolvedCanvas;\r\n const rect = resolvedCanvas.getBoundingClientRect();\r\n this.width = Math.round(rect.width || window.innerWidth);\r\n this.height = Math.round(rect.height || window.innerHeight);\r\n } else {\r\n this._createAutoCanvas();\r\n }\r\n\r\n try {\r\n if (!this.canvas) {\r\n throw new Error('No canvas element available.');\r\n }\r\n\r\n const ctx = this.canvas.getContext('2d');\r\n\r\n if (!ctx) {\r\n throw new Error('Could not get 2D rendering context.');\r\n }\r\n\r\n this.ctx = ctx;\r\n } catch (e) {\r\n console.error('[WaveParticles] Canvas error:', e);\r\n return;\r\n }\r\n\r\n this._onMouseMove = this._onMouseMove.bind(this);\r\n this._onMouseLeave = this._onMouseLeave.bind(this);\r\n this._onTouchMove = this._onTouchMove.bind(this);\r\n this._onTouchEnd = this._onTouchEnd.bind(this);\r\n this._onResize = this._onResize.bind(this);\r\n\r\n if (typeof document !== 'undefined') {\r\n window.addEventListener('resize', this._onResize);\r\n this.resize(); // Initial size setup\r\n }\r\n\r\n this.initParticles();\r\n this.start();\r\n }\r\n\r\n /**\r\n * Internal method to merge user configuration with library defaults.\r\n * @private\r\n */\r\n _mergeDefaults(userConfig) {\r\n const defaults = {\r\n waves: [\r\n {\r\n amplitude: 60,\r\n frequency: 0.003,\r\n speed: 0.006,\r\n yOffset: 0.55,\r\n color: 'rgba(248, 225, 231, 0.25)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.45\r\n },\r\n {\r\n amplitude: 50,\r\n frequency: 0.004,\r\n speed: 0.008,\r\n yOffset: 0.60,\r\n color: 'rgba(212, 165, 165, 0.2)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.5\r\n },\r\n {\r\n amplitude: 70,\r\n frequency: 0.0025,\r\n speed: 0.005,\r\n yOffset: 0.65,\r\n color: 'rgba(255, 255, 255, 0.2)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.4\r\n },\r\n {\r\n amplitude: 40,\r\n frequency: 0.0035,\r\n speed: 0.010,\r\n yOffset: 0.70,\r\n color: 'rgba(201, 169, 110, 0.12)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.55\r\n }\r\n ],\r\n particles: { countScale: 8000, maxCount: 180 },\r\n colors: {\r\n backgroundGradient: ['#fdfcfb', '#f7ede2', '#e8d5d0'],\r\n particleColorPrefixes: [\r\n 'rgba(248, 225, 231,',\r\n 'rgba(212, 165, 165,',\r\n 'rgba(201, 169, 110,',\r\n 'rgba(255, 255, 255,',\r\n 'rgba(232, 213, 208,'\r\n ],\r\n mouseGlowStops: [\r\n { offset: 0, color: 'rgba(255, 255, 255, 0.08)' },\r\n { offset: 0.5, color: 'rgba(248, 225, 231, 0.04)' },\r\n { offset: 1, color: 'rgba(248, 225, 231, 0)' }\r\n ]\r\n }\r\n };\r\n\r\n const result = {};\r\n\r\n for (const key in defaults) {\r\n if (!defaults.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n if (!(userConfig && userConfig[key])) {\r\n result[key] = JSON.parse(JSON.stringify(defaults[key]));\r\n } else if (typeof defaults[key] === 'object' && !Array.isArray(defaults[key]) && typeof userConfig[key] === 'object') {\r\n result[key] = Object.assign({}, defaults[key], userConfig[key]);\r\n } else if (key === 'waves') {\r\n result.waves = Array.isArray(userConfig.waves) ? [...userConfig.waves] : JSON.parse(JSON.stringify(defaults.waves));\r\n } else {\r\n result[key] = userConfig[key];\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Automatically creates and injects a canvas element into the DOM if none was provided.\r\n * @private\r\n */\r\n _createAutoCanvas() {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const el = document.createElement('canvas');\r\n\r\n el.id = 'wave-particles-canvas';\r\n\r\n Object.assign(el.style, {\r\n position: 'fixed',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n zIndex: '-1',\r\n pointerEvents: 'none'\r\n });\r\n\r\n const body = document.body;\r\n\r\n if (!body) {\r\n return;\r\n }\r\n\r\n body.insertBefore(el, body.firstChild);\r\n this.canvas = el;\r\n this.width = window.innerWidth;\r\n this.height = window.innerHeight;\r\n }\r\n\r\n /**\r\n * Event handler for window resize events, including debouncing to prevent performance issues.\r\n * @private\r\n */\r\n _onResize() {\r\n if (this._resizeTimeout) clearTimeout(this._resizeTimeout);\r\n // Debounce resize to prevent flashing and high CPU usage\r\n this._resizeTimeout = setTimeout(() => {\r\n this.resize();\r\n }, 250);\r\n }\r\n\r\n /**\r\n * Recalculates canvas dimensions based on its display size and Device Pixel Ratio.\r\n * Re-initializes particles to match the new surface area.\r\n */\r\n resize() {\r\n if (!this.canvas) {\r\n return;\r\n }\r\n\r\n const rect = this.canvas.getBoundingClientRect();\r\n const dpr = window.devicePixelRatio || 1;\r\n\r\n // Use CSS pixels for logical dimensions.\r\n // Fallback to window size if canvas is not in layout (prevents the \"multiplication\" bug).\r\n const w = rect.width || window.innerWidth;\r\n const h = rect.height || window.innerHeight;\r\n\r\n this.width = w;\r\n this.height = h;\r\n\r\n // Set physical pixels for the canvas buffer\r\n this.canvas.width = Math.round(w * dpr);\r\n this.canvas.height = Math.round(h * dpr);\r\n\r\n // Scale the context to ensure all drawing operations use CSS pixels.\r\n // Re-get context if it was lost or not yet initialized.\r\n if (!this.ctx) {\r\n this.ctx = this.canvas.getContext('2d');\r\n }\r\n\r\n if (this.ctx) {\r\n this.ctx.scale(dpr, dpr);\r\n }\r\n\r\n if (this.isRunning) {\r\n this.initParticles();\r\n }\r\n }\r\n\r\n /**\r\n * Generates a new set of particles based on the current canvas area and configuration.\r\n */\r\n initParticles() {\r\n const { countScale = 8000, maxCount = 180 } = this.config.particles;\r\n\r\n const particleCount = Math.min(Math.floor((this.width * this.height) / (countScale > 0 ? countScale : 8000)), maxCount);\r\n\r\n this.particles = Array.from({ length: particleCount }, () => ({\r\n x: Math.random() * this.width,\r\n y: Math.random() * this.height,\r\n size: Math.random() * 4 + 1.5,\r\n speedX: (Math.random() - 0.5) * 0.4,\r\n speedY: (Math.random() - 0.5) * 0.4,\r\n opacity: Math.random() * 0.6 + 0.3,\r\n pulse: Math.random() * Math.PI * 2,\r\n pulseSpeed: Math.random() * 0.025 + 0.01,\r\n colorPrefix: this.config.colors.particleColorPrefixes[Math.floor(Math.random() * this.config.colors.particleColorPrefixes.length)]\r\n }));\r\n }\r\n\r\n _onMouseMove(e) {\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n if (!rect) {\r\n return;\r\n }\r\n\r\n // Calculate position relative to the canvas in CSS pixels\r\n this.targetMouseX = e.clientX - rect.left;\r\n this.targetMouseY = e.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onMouseLeave() {\r\n this.mouseActive = false;\r\n }\r\n\r\n _onTouchMove(e) {\r\n const touch = e.touches[0];\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n if (!touch || !rect) {\r\n return;\r\n }\r\n\r\n this.targetMouseX = touch.clientX - rect.left;\r\n this.targetMouseY = touch.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onTouchEnd() {\r\n this.mouseActive = false;\r\n }\r\n\r\n /**\r\n * Renders the radial gradient background across the entire canvas.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawBackground(ctx) {\r\n const colors = this.config.colors.backgroundGradient;\r\n\r\n const gradient = ctx.createRadialGradient(this.width / 2, this.height / 2, 0, this.width / 2, this.height / 2, Math.max(this.width, this.height) * 0.8);\r\n\r\n colors.forEach((c, i) => gradient.addColorStop(i / (colors.length - 1 || 1), c));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fillRect(0, 0, this.width, this.height);\r\n }\r\n\r\n /**\r\n * Renders all wave layers, accounting for mouse interaction and layer offsets.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawWaves(ctx) {\r\n const mouseNormX = this.mouseActive ? this.mouseX / this.width : -1;\r\n const mouseNormY = this.mouseActive ? this.mouseY / this.height : -1;\r\n\r\n for (let wi = 0; wi < this.config.waves.length; wi++) {\r\n const wave = this.config.waves[wi];\r\n const numLayers = Math.max(2, wave.layers || 2);\r\n\r\n for (let layer = 0; layer < numLayers; layer++) {\r\n const layerOpacity = (1 - layer / numLayers) * 0.5 + 0.5;\r\n\r\n ctx.beginPath();\r\n\r\n const baseY = this.height * wave.yOffset + layer * 3;\r\n\r\n const mouseEffect = this.mouseActive ? (mouseNormX - 0.5) * (wave.mouseInfluence || 0.45) * 150 : 0;\r\n\r\n ctx.moveTo(0, this.height);\r\n\r\n const step = Math.max(2, Math.floor(this.width / 480));\r\n\r\n for (let x = 0; x <= this.width; x += step) {\r\n let y = baseY;\r\n\r\n y += Math.sin(x * wave.frequency + this.time * wave.speed + layer * 0.1) * wave.amplitude;\r\n y += Math.sin(x * wave.frequency * 1.5 + this.time * wave.speed * 0.7 + wi) * wave.amplitude * 0.3;\r\n\r\n if (this.mouseActive) {\r\n const dx = x - this.mouseX;\r\n const dist = Math.abs(dx) / this.width;\r\n y += Math.sin(dist * Math.PI) * (mouseNormY > 0 ? (this.mouseY - this.height / 2) : 0) * 0.1 * (wave.mouseInfluence || 0.45);\r\n }\r\n\r\n y += mouseEffect * Math.sin((x / this.width) * Math.PI);\r\n\r\n ctx.lineTo(x, y);\r\n }\r\n\r\n ctx.lineTo(this.width, this.height);\r\n\r\n ctx.closePath();\r\n\r\n const baseColor = wave.color || 'rgba(139, 114, 86, 0.25)';\r\n\r\n ctx.fillStyle = baseColor.replace(/([\\d.]+)\\)$/, (m) => `${parseFloat(m) * layerOpacity})`);\r\n\r\n if (wave.lineWidth != null) {\r\n ctx.lineWidth = wave.lineWidth;\r\n }\r\n\r\n ctx.fill();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates and renders the particle system, including movement and mouse repulsion logic.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawParticles(ctx) {\r\n const maxDist = 150;\r\n\r\n for (const p of this.particles) {\r\n p.pulse += p.pulseSpeed;\r\n\r\n const currentOpacity = p.opacity * (Math.sin(p.pulse) * 0.3 + 0.7);\r\n\r\n if (this.mouseActive) {\r\n const dx = p.x - this.mouseX, dy = p.y - this.mouseY, dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (dist < maxDist && dist > 0.1) {\r\n const force = (1 - dist / maxDist) * 2;\r\n p.x += (dx / dist) * force;\r\n p.y += (dy / dist) * force;\r\n }\r\n }\r\n\r\n p.x += p.speedX;\r\n p.y += p.speedY;\r\n\r\n if (p.x < 0) {\r\n p.x = this.width;\r\n }\r\n\r\n if (p.x > this.width) {\r\n p.x = 0;\r\n }\r\n\r\n if (p.y < 0) {\r\n p.y = this.height;\r\n }\r\n\r\n if (p.y > this.height) {\r\n p.y = 0;\r\n }\r\n\r\n const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 2);\r\n\r\n grad.addColorStop(0, p.colorPrefix + currentOpacity + ')');\r\n\r\n grad.addColorStop(1, p.colorPrefix + '0)');\r\n\r\n ctx.beginPath();\r\n\r\n ctx.fillStyle = grad;\r\n\r\n ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2);\r\n\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n\r\n ctx.fillStyle = p.colorPrefix + (currentOpacity * 0.8) + ')';\r\n\r\n ctx.arc(p.x, p.y, p.size * 0.5, 0, Math.PI * 2);\r\n\r\n ctx.fill();\r\n }\r\n }\r\n\r\n /**\r\n * Renders a soft glow effect centered at the current mouse position.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawMouseGlow(ctx) {\r\n if (!this.mouseActive) {\r\n return;\r\n }\r\n\r\n const gradient = ctx.createRadialGradient(this.mouseX, this.mouseY, 0, this.mouseX, this.mouseY, 200);\r\n\r\n const stops = this.config.colors.mouseGlowStops;\r\n\r\n stops.forEach((s) => gradient.addColorStop(s.offset, s.color));\r\n\r\n ctx.beginPath();\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.arc(this.mouseX, this.mouseY, 200, 0, Math.PI * 2);\r\n\r\n ctx.fill();\r\n }\r\n\r\n /**\r\n * The main animation loop. Updates state and draws the next frame.\r\n */\r\n animate() {\r\n if (!this.ctx) {\r\n return;\r\n }\r\n\r\n this.time += 1;\r\n\r\n this.mouseX += (this.targetMouseX - this.mouseX) * 0.08;\r\n this.mouseY += (this.targetMouseY - this.mouseY) * 0.08;\r\n\r\n this.ctx.clearRect(0, 0, this.width, this.height);\r\n\r\n this.drawBackground(this.ctx);\r\n this.drawWaves(this.ctx);\r\n this.drawParticles(this.ctx);\r\n this.drawMouseGlow(this.ctx);\r\n\r\n if (this.isRunning) {\r\n requestAnimationFrame(() => this.animate());\r\n }\r\n }\r\n\r\n /**\r\n * Starts or resumes the animation loop and attaches interaction listeners.\r\n */\r\n start() {\r\n if (this.isRunning) {\r\n return;\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('mousemove', this._onMouseMove, { passive: true });\r\n window.addEventListener('touchmove', this._onTouchMove, { passive: false });\r\n window.addEventListener('touchend', this._onTouchEnd, { passive: true });\r\n window.addEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n\r\n this.isRunning = true;\r\n\r\n this.animate();\r\n }\r\n\r\n /**\r\n * Pauses the animation loop and detaches interaction listeners to save resources.\r\n */\r\n stop() {\r\n this.isRunning = false;\r\n\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('mousemove', this._onMouseMove);\r\n window.removeEventListener('touchmove', this._onTouchMove);\r\n window.removeEventListener('touchend', this._onTouchEnd);\r\n window.removeEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n }\r\n\r\n /**\r\n * Stops the animation, removes event listeners, and cleans up any auto-injected DOM elements.\r\n */\r\n destroy() {\r\n this.stop();\r\n\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('resize', this._onResize);\r\n }\r\n\r\n if (this.canvas && this.canvas.id === 'wave-particles-canvas' && this.canvas.parentNode) {\r\n this.canvas.parentNode.removeChild(this.canvas);\r\n }\r\n\r\n this.canvas = null;\r\n this.ctx = null;\r\n }\r\n}\r\n\r\nexport default WaveParticles;\r\n"],
5
+ "mappings": "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",
6
+ "names": ["WaveParticles", "options", "providedCanvasOrSelector", "config", "resolvedCanvas", "rect", "ctx", "e", "userConfig", "defaults", "result", "key", "el", "body", "dpr", "w", "h", "countScale", "maxCount", "particleCount", "touch", "colors", "gradient", "c", "i", "mouseNormX", "mouseNormY", "wi", "wave", "numLayers", "layer", "layerOpacity", "baseY", "mouseEffect", "step", "x", "y", "dx", "dist", "baseColor", "m", "p", "currentOpacity", "dy", "force", "grad", "src_default"]
7
7
  }
@@ -1,2 +1,2 @@
1
- (()=>{var l=class{constructor(e={}){let{canvas:i,config:t}=e||{};this.canvas=null,this.ctx=null,this.mouseX=0,this.mouseY=0,this.targetMouseX=-1e3,this.targetMouseY=-1e3,this.mouseActive=!1,this.width=0,this.height=0,this.config=this._mergeDefaults(t||{}),this.time=0,this.isRunning=!1,this.particles=[],this._resizeTimeout=null;let s=typeof document<"u"&&i?typeof i=="string"?document.querySelector(i):i:null;if(s){this.canvas=s;let o=s.getBoundingClientRect();this.width=Math.round(o.width||window.innerWidth),this.height=Math.round(o.height||window.innerHeight)}else this._createAutoCanvas();try{if(!this.canvas)throw new Error("No canvas element available.");let o=this.canvas.getContext("2d");if(!o)throw new Error("Could not get 2D rendering context.");this.ctx=o}catch(o){console.error("[WaveParticles] Canvas error:",o);return}this._onMouseMove=this._onMouseMove.bind(this),this._onMouseLeave=this._onMouseLeave.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onResize=this._onResize.bind(this),typeof document<"u"&&(window.addEventListener("resize",this._onResize),this.resize()),this.initParticles(),this.start()}_mergeDefaults(e){let i={waves:[{amplitude:60,frequency:.003,speed:.006,yOffset:.55,color:"rgba(248, 225, 231, 0.25)",lineWidth:1.5,mouseInfluence:.45},{amplitude:50,frequency:.004,speed:.008,yOffset:.6,color:"rgba(212, 165, 165, 0.2)",lineWidth:1,mouseInfluence:.5},{amplitude:70,frequency:.0025,speed:.005,yOffset:.65,color:"rgba(255, 255, 255, 0.2)",lineWidth:1.5,mouseInfluence:.4},{amplitude:40,frequency:.0035,speed:.01,yOffset:.7,color:"rgba(201, 169, 110, 0.12)",lineWidth:1,mouseInfluence:.55}],particles:{countScale:8e3,maxCount:180},colors:{backgroundGradient:["#fdfcfb","#f7ede2","#e8d5d0"],particleColorPrefixes:["rgba(248, 225, 231,","rgba(212, 165, 165,","rgba(201, 169, 110,","rgba(255, 255, 255,","rgba(232, 213, 208,"],mouseGlowStops:[{offset:0,color:"rgba(255, 255, 255, 0.08)"},{offset:.5,color:"rgba(248, 225, 231, 0.04)"},{offset:1,color:"rgba(248, 225, 231, 0)"}]}},t={};for(let s in i)i.hasOwnProperty(s)&&(e&&e[s]?typeof i[s]=="object"&&!Array.isArray(i[s])&&typeof e[s]=="object"?t[s]=Object.assign({},i[s],e[s]):s==="waves"?t.waves=Array.isArray(e.waves)?[...e.waves]:JSON.parse(JSON.stringify(i.waves)):t[s]=e[s]:t[s]=JSON.parse(JSON.stringify(i[s])));return t}_createAutoCanvas(){if(typeof document>"u")return;let e=document.createElement("canvas");e.id="wave-particles-canvas",Object.assign(e.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",zIndex:"-1",pointerEvents:"none"});let i=document.body;i&&(i.insertBefore(e,i.firstChild),this.canvas=e,this.width=window.innerWidth,this.height=window.innerHeight)}_onResize(){this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this.resize()},250)}resize(){if(!this.canvas)return;let e=this.canvas.getBoundingClientRect(),i,t,s=parseInt(this.canvas.getAttribute("width"),10),o=parseInt(this.canvas.getAttribute("height"),10);s&&o?(i=Math.round(e.width||s),t=Math.round(e.height||o)):(i=window.innerWidth,t=window.innerHeight,!this.canvas.parentNode&&document.body&&document.body.insertBefore(this.canvas,document.body.firstChild)),this.width=i,this.height=t;let n=window.devicePixelRatio||1;this.canvas.width=Math.round(i*n),this.canvas.height=Math.round(t*n),this.ctx&&this.isRunning&&this.initParticles()}initParticles(){let{countScale:e=8e3,maxCount:i=180}=this.config.particles,t=Math.min(Math.floor(this.width*this.height/(e>0?e:8e3)),i);this.particles=Array.from({length:t},()=>({x:Math.random()*this.width,y:Math.random()*this.height,size:Math.random()*4+1.5,speedX:(Math.random()-.5)*.4,speedY:(Math.random()-.5)*.4,opacity:Math.random()*.6+.3,pulse:Math.random()*Math.PI*2,pulseSpeed:Math.random()*.025+.01,colorPrefix:this.config.colors.particleColorPrefixes[Math.floor(Math.random()*this.config.colors.particleColorPrefixes.length)]}))}_onMouseMove(e){let i=this.canvas.getBoundingClientRect();i&&(this.targetMouseX=e.clientX-i.left,this.targetMouseY=e.clientY-i.top,this.mouseActive=!0)}_onMouseLeave(){this.mouseActive=!1}_onTouchMove(e){let i=e.touches[0],t=this.canvas.getBoundingClientRect();!i||!t||(this.targetMouseX=i.clientX-t.left,this.targetMouseY=i.clientY-t.top,this.mouseActive=!0)}_onTouchEnd(){this.mouseActive=!1}drawBackground(e){let i=this.config.colors.backgroundGradient,t=e.createRadialGradient(this.width/2,this.height/2,0,this.width/2,this.height/2,Math.max(this.width,this.height)*.8);i.forEach((s,o)=>t.addColorStop(o/(i.length-1||1),s)),e.fillStyle=t,e.fillRect(0,0,this.width,this.height)}drawWaves(e){let i=this.mouseActive?this.mouseX/this.width:-1,t=this.mouseActive?this.mouseY/this.height:-1;for(let s=0;s<this.config.waves.length;s++){let o=this.config.waves[s],n=Math.max(2,o.layers||2);for(let h=0;h<n;h++){let r=(1-h/n)*.5+.5;e.beginPath();let d=this.height*o.yOffset+h*3,f=this.mouseActive?(i-.5)*(o.mouseInfluence||.45)*150:0;e.moveTo(0,this.height);let m=Math.max(2,Math.floor(this.width/480));for(let a=0;a<=this.width;a+=m){let c=d;if(c+=Math.sin(a*o.frequency+this.time*o.speed+h*.1)*o.amplitude,c+=Math.sin(a*o.frequency*1.5+this.time*o.speed*.7+s)*o.amplitude*.3,this.mouseActive){let w=a-this.mouseX,g=Math.abs(w)/this.width;c+=Math.sin(g*Math.PI)*(t>0?this.mouseY-this.height/2:0)*.1*(o.mouseInfluence||.45)}c+=f*Math.sin(a/this.width*Math.PI),e.lineTo(a,c)}e.lineTo(this.width,this.height),e.closePath();let v=o.color||"rgba(139, 114, 86, 0.25)";e.fillStyle=v.replace(/([\d.]+)\)$/,a=>`${parseFloat(a)*r})`),o.lineWidth!=null&&(e.lineWidth=o.lineWidth),e.fill()}}}drawParticles(e){for(let t of this.particles){t.pulse+=t.pulseSpeed;let s=t.opacity*(Math.sin(t.pulse)*.3+.7);if(this.mouseActive){let n=t.x-this.mouseX,h=t.y-this.mouseY,r=Math.sqrt(n*n+h*h);if(r<150&&r>.1){let d=(1-r/150)*2;t.x+=n/r*d,t.y+=h/r*d}}t.x+=t.speedX,t.y+=t.speedY,t.x<0&&(t.x=this.width),t.x>this.width&&(t.x=0),t.y<0&&(t.y=this.height),t.y>this.height&&(t.y=0);let o=e.createRadialGradient(t.x,t.y,0,t.x,t.y,t.size*2);o.addColorStop(0,t.colorPrefix+s+")"),o.addColorStop(1,t.colorPrefix+"0)"),e.beginPath(),e.fillStyle=o,e.arc(t.x,t.y,t.size*2,0,Math.PI*2),e.fill(),e.beginPath(),e.fillStyle=t.colorPrefix+s*.8+")",e.arc(t.x,t.y,t.size*.5,0,Math.PI*2),e.fill()}}drawMouseGlow(e){if(!this.mouseActive)return;let i=e.createRadialGradient(this.mouseX,this.mouseY,0,this.mouseX,this.mouseY,200);this.config.colors.mouseGlowStops.forEach(s=>i.addColorStop(s.offset,s.color)),e.beginPath(),e.fillStyle=i,e.arc(this.mouseX,this.mouseY,200,0,Math.PI*2),e.fill()}animate(){this.ctx&&(this.time+=1,this.mouseX+=(this.targetMouseX-this.mouseX)*.08,this.mouseY+=(this.targetMouseY-this.mouseY)*.08,this.ctx.clearRect(0,0,this.width,this.height),this.drawBackground(this.ctx),this.drawWaves(this.ctx),this.drawParticles(this.ctx),this.drawMouseGlow(this.ctx),this.isRunning&&requestAnimationFrame(()=>this.animate()))}start(){this.isRunning||(typeof window<"u"&&(window.addEventListener("mousemove",this._onMouseMove,{passive:!0}),window.addEventListener("touchmove",this._onTouchMove,{passive:!1}),window.addEventListener("touchend",this._onTouchEnd,{passive:!0}),window.addEventListener("mouseleave",this._onMouseLeave)),this.isRunning=!0,this.animate())}stop(){this.isRunning=!1,typeof window<"u"&&(window.removeEventListener("mousemove",this._onMouseMove),window.removeEventListener("touchmove",this._onTouchMove),window.removeEventListener("touchend",this._onTouchEnd),window.removeEventListener("mouseleave",this._onMouseLeave))}destroy(){this.stop(),typeof window<"u"&&window.removeEventListener("resize",this._onResize),this.canvas&&this.canvas.id==="wave-particles-canvas"&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas),this.canvas=null,this.ctx=null}},u=l;typeof window<"u"?window.WaveParticles=u:typeof globalThis<"u"&&(globalThis.WaveParticles=u);})();
1
+ (()=>{var l=class{constructor(e={}){let{canvas:i,config:t}=e||{};this.canvas=null,this.ctx=null,this.mouseX=0,this.mouseY=0,this.targetMouseX=-1e3,this.targetMouseY=-1e3,this.mouseActive=!1,this.width=0,this.height=0,this.config=this._mergeDefaults(t||{}),this.time=0,this.isRunning=!1,this.particles=[],this._resizeTimeout=null;let s=typeof document<"u"&&i?typeof i=="string"?document.querySelector(i):i:null;if(s){this.canvas=s;let o=s.getBoundingClientRect();this.width=Math.round(o.width||window.innerWidth),this.height=Math.round(o.height||window.innerHeight)}else this._createAutoCanvas();try{if(!this.canvas)throw new Error("No canvas element available.");let o=this.canvas.getContext("2d");if(!o)throw new Error("Could not get 2D rendering context.");this.ctx=o}catch(o){console.error("[WaveParticles] Canvas error:",o);return}this._onMouseMove=this._onMouseMove.bind(this),this._onMouseLeave=this._onMouseLeave.bind(this),this._onTouchMove=this._onTouchMove.bind(this),this._onTouchEnd=this._onTouchEnd.bind(this),this._onResize=this._onResize.bind(this),typeof document<"u"&&(window.addEventListener("resize",this._onResize),this.resize()),this.initParticles(),this.start()}_mergeDefaults(e){let i={waves:[{amplitude:60,frequency:.003,speed:.006,yOffset:.55,color:"rgba(248, 225, 231, 0.25)",lineWidth:1.5,mouseInfluence:.45},{amplitude:50,frequency:.004,speed:.008,yOffset:.6,color:"rgba(212, 165, 165, 0.2)",lineWidth:1,mouseInfluence:.5},{amplitude:70,frequency:.0025,speed:.005,yOffset:.65,color:"rgba(255, 255, 255, 0.2)",lineWidth:1.5,mouseInfluence:.4},{amplitude:40,frequency:.0035,speed:.01,yOffset:.7,color:"rgba(201, 169, 110, 0.12)",lineWidth:1,mouseInfluence:.55}],particles:{countScale:8e3,maxCount:180},colors:{backgroundGradient:["#fdfcfb","#f7ede2","#e8d5d0"],particleColorPrefixes:["rgba(248, 225, 231,","rgba(212, 165, 165,","rgba(201, 169, 110,","rgba(255, 255, 255,","rgba(232, 213, 208,"],mouseGlowStops:[{offset:0,color:"rgba(255, 255, 255, 0.08)"},{offset:.5,color:"rgba(248, 225, 231, 0.04)"},{offset:1,color:"rgba(248, 225, 231, 0)"}]}},t={};for(let s in i)i.hasOwnProperty(s)&&(e&&e[s]?typeof i[s]=="object"&&!Array.isArray(i[s])&&typeof e[s]=="object"?t[s]=Object.assign({},i[s],e[s]):s==="waves"?t.waves=Array.isArray(e.waves)?[...e.waves]:JSON.parse(JSON.stringify(i.waves)):t[s]=e[s]:t[s]=JSON.parse(JSON.stringify(i[s])));return t}_createAutoCanvas(){if(typeof document>"u")return;let e=document.createElement("canvas");e.id="wave-particles-canvas",Object.assign(e.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",zIndex:"-1",pointerEvents:"none"});let i=document.body;i&&(i.insertBefore(e,i.firstChild),this.canvas=e,this.width=window.innerWidth,this.height=window.innerHeight)}_onResize(){this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeTimeout=setTimeout(()=>{this.resize()},250)}resize(){if(!this.canvas)return;let e=this.canvas.getBoundingClientRect(),i=window.devicePixelRatio||1,t=e.width||window.innerWidth,s=e.height||window.innerHeight;this.width=t,this.height=s,this.canvas.width=Math.round(t*i),this.canvas.height=Math.round(s*i),this.ctx||(this.ctx=this.canvas.getContext("2d")),this.ctx&&this.ctx.scale(i,i),this.isRunning&&this.initParticles()}initParticles(){let{countScale:e=8e3,maxCount:i=180}=this.config.particles,t=Math.min(Math.floor(this.width*this.height/(e>0?e:8e3)),i);this.particles=Array.from({length:t},()=>({x:Math.random()*this.width,y:Math.random()*this.height,size:Math.random()*4+1.5,speedX:(Math.random()-.5)*.4,speedY:(Math.random()-.5)*.4,opacity:Math.random()*.6+.3,pulse:Math.random()*Math.PI*2,pulseSpeed:Math.random()*.025+.01,colorPrefix:this.config.colors.particleColorPrefixes[Math.floor(Math.random()*this.config.colors.particleColorPrefixes.length)]}))}_onMouseMove(e){let i=this.canvas.getBoundingClientRect();i&&(this.targetMouseX=e.clientX-i.left,this.targetMouseY=e.clientY-i.top,this.mouseActive=!0)}_onMouseLeave(){this.mouseActive=!1}_onTouchMove(e){let i=e.touches[0],t=this.canvas.getBoundingClientRect();!i||!t||(this.targetMouseX=i.clientX-t.left,this.targetMouseY=i.clientY-t.top,this.mouseActive=!0)}_onTouchEnd(){this.mouseActive=!1}drawBackground(e){let i=this.config.colors.backgroundGradient,t=e.createRadialGradient(this.width/2,this.height/2,0,this.width/2,this.height/2,Math.max(this.width,this.height)*.8);i.forEach((s,o)=>t.addColorStop(o/(i.length-1||1),s)),e.fillStyle=t,e.fillRect(0,0,this.width,this.height)}drawWaves(e){let i=this.mouseActive?this.mouseX/this.width:-1,t=this.mouseActive?this.mouseY/this.height:-1;for(let s=0;s<this.config.waves.length;s++){let o=this.config.waves[s],r=Math.max(2,o.layers||2);for(let n=0;n<r;n++){let a=(1-n/r)*.5+.5;e.beginPath();let d=this.height*o.yOffset+n*3,f=this.mouseActive?(i-.5)*(o.mouseInfluence||.45)*150:0;e.moveTo(0,this.height);let m=Math.max(2,Math.floor(this.width/480));for(let h=0;h<=this.width;h+=m){let c=d;if(c+=Math.sin(h*o.frequency+this.time*o.speed+n*.1)*o.amplitude,c+=Math.sin(h*o.frequency*1.5+this.time*o.speed*.7+s)*o.amplitude*.3,this.mouseActive){let w=h-this.mouseX,g=Math.abs(w)/this.width;c+=Math.sin(g*Math.PI)*(t>0?this.mouseY-this.height/2:0)*.1*(o.mouseInfluence||.45)}c+=f*Math.sin(h/this.width*Math.PI),e.lineTo(h,c)}e.lineTo(this.width,this.height),e.closePath();let v=o.color||"rgba(139, 114, 86, 0.25)";e.fillStyle=v.replace(/([\d.]+)\)$/,h=>`${parseFloat(h)*a})`),o.lineWidth!=null&&(e.lineWidth=o.lineWidth),e.fill()}}}drawParticles(e){for(let t of this.particles){t.pulse+=t.pulseSpeed;let s=t.opacity*(Math.sin(t.pulse)*.3+.7);if(this.mouseActive){let r=t.x-this.mouseX,n=t.y-this.mouseY,a=Math.sqrt(r*r+n*n);if(a<150&&a>.1){let d=(1-a/150)*2;t.x+=r/a*d,t.y+=n/a*d}}t.x+=t.speedX,t.y+=t.speedY,t.x<0&&(t.x=this.width),t.x>this.width&&(t.x=0),t.y<0&&(t.y=this.height),t.y>this.height&&(t.y=0);let o=e.createRadialGradient(t.x,t.y,0,t.x,t.y,t.size*2);o.addColorStop(0,t.colorPrefix+s+")"),o.addColorStop(1,t.colorPrefix+"0)"),e.beginPath(),e.fillStyle=o,e.arc(t.x,t.y,t.size*2,0,Math.PI*2),e.fill(),e.beginPath(),e.fillStyle=t.colorPrefix+s*.8+")",e.arc(t.x,t.y,t.size*.5,0,Math.PI*2),e.fill()}}drawMouseGlow(e){if(!this.mouseActive)return;let i=e.createRadialGradient(this.mouseX,this.mouseY,0,this.mouseX,this.mouseY,200);this.config.colors.mouseGlowStops.forEach(s=>i.addColorStop(s.offset,s.color)),e.beginPath(),e.fillStyle=i,e.arc(this.mouseX,this.mouseY,200,0,Math.PI*2),e.fill()}animate(){this.ctx&&(this.time+=1,this.mouseX+=(this.targetMouseX-this.mouseX)*.08,this.mouseY+=(this.targetMouseY-this.mouseY)*.08,this.ctx.clearRect(0,0,this.width,this.height),this.drawBackground(this.ctx),this.drawWaves(this.ctx),this.drawParticles(this.ctx),this.drawMouseGlow(this.ctx),this.isRunning&&requestAnimationFrame(()=>this.animate()))}start(){this.isRunning||(typeof window<"u"&&(window.addEventListener("mousemove",this._onMouseMove,{passive:!0}),window.addEventListener("touchmove",this._onTouchMove,{passive:!1}),window.addEventListener("touchend",this._onTouchEnd,{passive:!0}),window.addEventListener("mouseleave",this._onMouseLeave)),this.isRunning=!0,this.animate())}stop(){this.isRunning=!1,typeof window<"u"&&(window.removeEventListener("mousemove",this._onMouseMove),window.removeEventListener("touchmove",this._onTouchMove),window.removeEventListener("touchend",this._onTouchEnd),window.removeEventListener("mouseleave",this._onMouseLeave))}destroy(){this.stop(),typeof window<"u"&&window.removeEventListener("resize",this._onResize),this.canvas&&this.canvas.id==="wave-particles-canvas"&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas),this.canvas=null,this.ctx=null}},u=l;typeof window<"u"?window.WaveParticles=u:typeof globalThis<"u"&&(globalThis.WaveParticles=u);})();
2
2
  //# sourceMappingURL=wave-particles.iife.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js", "../src/browser.js"],
4
- "sourcesContent": ["/**\r\n * js-waves-particles\r\n * A canvas-based wave and particle animation library with mouse-reactive effects.\r\n * Developed by Luis 'PlatinumBlade' Moniz.\r\n */\r\n\r\nclass WaveParticles {\r\n /**\r\n * Initializes a new WaveParticles animation engine.\r\n *\r\n * @param {import('./index').WaveParticlesOptions} [options] - Configuration for the engine.\r\n * @param {HTMLCanvasElement|string} [options.canvas] - The target canvas element or a CSS selector (e.g., '#bg'). If omitted, a full-screen fixed canvas is automatically created.\r\n * @param {import('./index').WaveParticlesConfig} [options.config] - Visual parameters for waves, particles, and colors.\r\n */\r\n constructor(options = {}) {\r\n const {canvas: providedCanvasOrSelector, config} = options || {};\r\n\r\n // --- State ---\r\n this.canvas = null;\r\n this.ctx = null;\r\n this.mouseX = 0;\r\n this.mouseY = 0;\r\n this.targetMouseX = -1000;\r\n this.targetMouseY = -1000;\r\n this.mouseActive = false;\r\n this.width = 0;\r\n this.height = 0;\r\n this.config = this._mergeDefaults(config || {});\r\n this.time = 0;\r\n this.isRunning = false;\r\n this.particles = [];\r\n this._resizeTimeout = null;\r\n\r\n const resolvedCanvas = typeof document !== 'undefined' && providedCanvasOrSelector ? (() => {\r\n if (typeof providedCanvasOrSelector === 'string') {\r\n return /** @type {HTMLCanvasElement|null} */ (document.querySelector(providedCanvasOrSelector));\r\n }\r\n\r\n return /** @type {HTMLCanvasElement | null} */ (providedCanvasOrSelector);\r\n })() : null;\r\n\r\n if (resolvedCanvas) {\r\n this.canvas = resolvedCanvas;\r\n const rect = resolvedCanvas.getBoundingClientRect();\r\n this.width = Math.round(rect.width || window.innerWidth);\r\n this.height = Math.round(rect.height || window.innerHeight);\r\n } else {\r\n this._createAutoCanvas();\r\n }\r\n\r\n try {\r\n if (!this.canvas) {\r\n throw new Error('No canvas element available.');\r\n }\r\n\r\n const ctx = this.canvas.getContext('2d');\r\n\r\n if (!ctx) {\r\n throw new Error('Could not get 2D rendering context.');\r\n }\r\n\r\n this.ctx = ctx;\r\n } catch (e) {\r\n console.error('[WaveParticles] Canvas error:', e);\r\n return;\r\n }\r\n\r\n this._onMouseMove = this._onMouseMove.bind(this);\r\n this._onMouseLeave = this._onMouseLeave.bind(this);\r\n this._onTouchMove = this._onTouchMove.bind(this);\r\n this._onTouchEnd = this._onTouchEnd.bind(this);\r\n this._onResize = this._onResize.bind(this);\r\n\r\n if (typeof document !== 'undefined') {\r\n window.addEventListener('resize', this._onResize);\r\n this.resize(); // Initial size setup\r\n }\r\n\r\n this.initParticles();\r\n this.start();\r\n }\r\n\r\n /**\r\n * Internal method to merge user configuration with library defaults.\r\n * @private\r\n */\r\n _mergeDefaults(userConfig) {\r\n const defaults = {\r\n waves: [\r\n {\r\n amplitude: 60,\r\n frequency: 0.003,\r\n speed: 0.006,\r\n yOffset: 0.55,\r\n color: 'rgba(248, 225, 231, 0.25)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.45\r\n },\r\n {\r\n amplitude: 50,\r\n frequency: 0.004,\r\n speed: 0.008,\r\n yOffset: 0.60,\r\n color: 'rgba(212, 165, 165, 0.2)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.5\r\n },\r\n {\r\n amplitude: 70,\r\n frequency: 0.0025,\r\n speed: 0.005,\r\n yOffset: 0.65,\r\n color: 'rgba(255, 255, 255, 0.2)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.4\r\n },\r\n {\r\n amplitude: 40,\r\n frequency: 0.0035,\r\n speed: 0.010,\r\n yOffset: 0.70,\r\n color: 'rgba(201, 169, 110, 0.12)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.55\r\n }\r\n ],\r\n particles: {countScale: 8000, maxCount: 180},\r\n colors: {\r\n backgroundGradient: ['#fdfcfb', '#f7ede2', '#e8d5d0'],\r\n particleColorPrefixes: [\r\n 'rgba(248, 225, 231,',\r\n 'rgba(212, 165, 165,',\r\n 'rgba(201, 169, 110,',\r\n 'rgba(255, 255, 255,',\r\n 'rgba(232, 213, 208,'\r\n ],\r\n mouseGlowStops: [\r\n {offset: 0, color: 'rgba(255, 255, 255, 0.08)'},\r\n {offset: 0.5, color: 'rgba(248, 225, 231, 0.04)'},\r\n {offset: 1, color: 'rgba(248, 225, 231, 0)'}\r\n ]\r\n }\r\n };\r\n\r\n const result = {};\r\n\r\n for (const key in defaults) {\r\n if (!defaults.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n if (!(userConfig && userConfig[key])) {\r\n result[key] = JSON.parse(JSON.stringify(defaults[key]));\r\n } else if (typeof defaults[key] === 'object' && !Array.isArray(defaults[key]) && typeof userConfig[key] === 'object') {\r\n result[key] = Object.assign({}, defaults[key], userConfig[key]);\r\n } else if (key === 'waves') {\r\n result.waves = Array.isArray(userConfig.waves) ? [...userConfig.waves] : JSON.parse(JSON.stringify(defaults.waves));\r\n } else {\r\n result[key] = userConfig[key];\r\n }\r\n }\r\n \r\n return result;\r\n }\r\n\r\n /**\r\n * Automatically creates and injects a canvas element into the DOM if none was provided.\r\n * @private\r\n */\r\n _createAutoCanvas() {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const el = document.createElement('canvas');\r\n\r\n el.id = 'wave-particles-canvas';\r\n\r\n Object.assign(el.style, {\r\n position: 'fixed',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n zIndex: '-1',\r\n pointerEvents: 'none'\r\n });\r\n\r\n const body = document.body;\r\n\r\n if (!body) {\r\n return;\r\n }\r\n\r\n body.insertBefore(el, body.firstChild);\r\n this.canvas = el;\r\n this.width = window.innerWidth;\r\n this.height = window.innerHeight;\r\n }\r\n\r\n /**\r\n * Event handler for window resize events, including debouncing to prevent performance issues.\r\n * @private\r\n */\r\n _onResize() {\r\n if (this._resizeTimeout) clearTimeout(this._resizeTimeout);\r\n // Debounce resize to prevent flashing and high CPU usage\r\n this._resizeTimeout = setTimeout(() => {\r\n this.resize();\r\n }, 250);\r\n }\r\n\r\n /**\r\n * Recalculates canvas dimensions based on its display size and Device Pixel Ratio.\r\n * Re-initializes particles to match the new surface area.\r\n */\r\n resize() {\r\n if (!this.canvas) {\r\n return;\r\n }\r\n\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n let w, h;\r\n\r\n const attrW = parseInt(this.canvas.getAttribute('width'), 10);\r\n const attrH = parseInt(this.canvas.getAttribute('height'), 10);\r\n\r\n if (attrW && attrH) {\r\n w = Math.round(rect.width || attrW);\r\n h = Math.round(rect.height || attrH);\r\n } else {\r\n w = window.innerWidth;\r\n h = window.innerHeight;\r\n\r\n if (!this.canvas.parentNode && document.body) {\r\n document.body.insertBefore(this.canvas, document.body.firstChild);\r\n }\r\n }\r\n \r\n this.width = w;\r\n this.height = h;\r\n\r\n const dpr = window.devicePixelRatio || 1;\r\n\r\n this.canvas.width = Math.round(w * dpr);\r\n this.canvas.height = Math.round(h * dpr);\r\n\r\n if (this.ctx && this.isRunning) {\r\n this.initParticles();\r\n }\r\n }\r\n\r\n /**\r\n * Generates a new set of particles based on the current canvas area and configuration.\r\n */\r\n initParticles() {\r\n const {countScale = 8000, maxCount = 180} = this.config.particles;\r\n\r\n const particleCount = Math.min(Math.floor((this.width * this.height) / (countScale > 0 ? countScale : 8000)), maxCount);\r\n\r\n this.particles = Array.from({length: particleCount}, () => ({\r\n x: Math.random() * this.width,\r\n y: Math.random() * this.height,\r\n size: Math.random() * 4 + 1.5,\r\n speedX: (Math.random() - 0.5) * 0.4,\r\n speedY: (Math.random() - 0.5) * 0.4,\r\n opacity: Math.random() * 0.6 + 0.3,\r\n pulse: Math.random() * Math.PI * 2,\r\n pulseSpeed: Math.random() * 0.025 + 0.01,\r\n colorPrefix: this.config.colors.particleColorPrefixes[Math.floor(Math.random() * this.config.colors.particleColorPrefixes.length)]\r\n }));\r\n }\r\n\r\n _onMouseMove(e) {\r\n const rect = this.canvas.getBoundingClientRect();\r\n \r\n if (!rect) {\r\n return;\r\n }\r\n\r\n // Calculate position relative to the canvas in CSS pixels\r\n this.targetMouseX = e.clientX - rect.left;\r\n this.targetMouseY = e.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onMouseLeave() {\r\n this.mouseActive = false;\r\n }\r\n\r\n _onTouchMove(e) {\r\n const touch = e.touches[0];\r\n const rect = this.canvas.getBoundingClientRect();\r\n \r\n if (!touch || !rect) {\r\n return;\r\n }\r\n\r\n this.targetMouseX = touch.clientX - rect.left;\r\n this.targetMouseY = touch.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onTouchEnd() {\r\n this.mouseActive = false;\r\n }\r\n\r\n /**\r\n * Renders the radial gradient background across the entire canvas.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawBackground(ctx) {\r\n const colors = this.config.colors.backgroundGradient;\r\n \r\n const gradient = ctx.createRadialGradient(this.width / 2, this.height / 2, 0, this.width / 2, this.height / 2, Math.max(this.width, this.height) * 0.8);\r\n \r\n colors.forEach((c, i) => gradient.addColorStop(i / (colors.length - 1 || 1), c));\r\n \r\n ctx.fillStyle = gradient;\r\n \r\n ctx.fillRect(0, 0, this.width, this.height);\r\n }\r\n\r\n /**\r\n * Renders all wave layers, accounting for mouse interaction and layer offsets.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawWaves(ctx) {\r\n const mouseNormX = this.mouseActive ? this.mouseX / this.width : -1;\r\n const mouseNormY = this.mouseActive ? this.mouseY / this.height : -1;\r\n\r\n for (let wi = 0; wi < this.config.waves.length; wi++) {\r\n const wave = this.config.waves[wi];\r\n const numLayers = Math.max(2, wave.layers || 2);\r\n\r\n for (let layer = 0; layer < numLayers; layer++) {\r\n const layerOpacity = (1 - layer / numLayers) * 0.5 + 0.5;\r\n \r\n ctx.beginPath();\r\n \r\n const baseY = this.height * wave.yOffset + layer * 3;\r\n \r\n const mouseEffect = this.mouseActive ? (mouseNormX - 0.5) * (wave.mouseInfluence || 0.45) * 150 : 0;\r\n \r\n ctx.moveTo(0, this.height);\r\n\r\n const step = Math.max(2, Math.floor(this.width / 480));\r\n \r\n for (let x = 0; x <= this.width; x += step) {\r\n let y = baseY;\r\n \r\n y += Math.sin(x * wave.frequency + this.time * wave.speed + layer * 0.1) * wave.amplitude;\r\n y += Math.sin(x * wave.frequency * 1.5 + this.time * wave.speed * 0.7 + wi) * wave.amplitude * 0.3;\r\n \r\n if (this.mouseActive) {\r\n const dx = x - this.mouseX;\r\n const dist = Math.abs(dx) / this.width;\r\n y += Math.sin(dist * Math.PI) * (mouseNormY > 0 ? (this.mouseY - this.height / 2) : 0) * 0.1 * (wave.mouseInfluence || 0.45);\r\n }\r\n \r\n y += mouseEffect * Math.sin((x / this.width) * Math.PI);\r\n \r\n ctx.lineTo(x, y);\r\n }\r\n \r\n ctx.lineTo(this.width, this.height);\r\n \r\n ctx.closePath();\r\n \r\n const baseColor = wave.color || 'rgba(139, 114, 86, 0.25)';\r\n \r\n ctx.fillStyle = baseColor.replace(/([\\d.]+)\\)$/, (m) => `${parseFloat(m) * layerOpacity})`);\r\n \r\n if (wave.lineWidth != null) {\r\n ctx.lineWidth = wave.lineWidth;\r\n }\r\n \r\n ctx.fill();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates and renders the particle system, including movement and mouse repulsion logic.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawParticles(ctx) {\r\n const maxDist = 150;\r\n \r\n for (const p of this.particles) {\r\n p.pulse += p.pulseSpeed;\r\n \r\n const currentOpacity = p.opacity * (Math.sin(p.pulse) * 0.3 + 0.7);\r\n \r\n if (this.mouseActive) {\r\n const dx = p.x - this.mouseX, dy = p.y - this.mouseY, dist = Math.sqrt(dx * dx + dy * dy);\r\n \r\n if (dist < maxDist && dist > 0.1) {\r\n const force = (1 - dist / maxDist) * 2;\r\n p.x += (dx / dist) * force;\r\n p.y += (dy / dist) * force;\r\n }\r\n }\r\n \r\n p.x += p.speedX;\r\n p.y += p.speedY;\r\n \r\n if (p.x < 0) {\r\n p.x = this.width;\r\n }\r\n \r\n if (p.x > this.width) {\r\n p.x = 0;\r\n }\r\n \r\n if (p.y < 0) {\r\n p.y = this.height;\r\n }\r\n \r\n if (p.y > this.height) {\r\n p.y = 0;\r\n }\r\n\r\n const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 2);\r\n \r\n grad.addColorStop(0, p.colorPrefix + currentOpacity + ')');\r\n \r\n grad.addColorStop(1, p.colorPrefix + '0)');\r\n \r\n ctx.beginPath();\r\n \r\n ctx.fillStyle = grad;\r\n \r\n ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2);\r\n \r\n ctx.fill();\r\n \r\n ctx.beginPath();\r\n \r\n ctx.fillStyle = p.colorPrefix + (currentOpacity * 0.8) + ')';\r\n \r\n ctx.arc(p.x, p.y, p.size * 0.5, 0, Math.PI * 2);\r\n \r\n ctx.fill();\r\n }\r\n }\r\n\r\n /**\r\n * Renders a soft glow effect centered at the current mouse position.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawMouseGlow(ctx) {\r\n if (!this.mouseActive) {\r\n return;\r\n }\r\n \r\n const gradient = ctx.createRadialGradient(this.mouseX, this.mouseY, 0, this.mouseX, this.mouseY, 200);\r\n \r\n const stops = this.config.colors.mouseGlowStops;\r\n \r\n stops.forEach((s) => gradient.addColorStop(s.offset, s.color));\r\n \r\n ctx.beginPath();\r\n \r\n ctx.fillStyle = gradient;\r\n \r\n ctx.arc(this.mouseX, this.mouseY, 200, 0, Math.PI * 2);\r\n \r\n ctx.fill();\r\n }\r\n\r\n /**\r\n * The main animation loop. Updates state and draws the next frame.\r\n */\r\n animate() {\r\n if (!this.ctx) {\r\n return;\r\n }\r\n \r\n this.time += 1;\r\n \r\n this.mouseX += (this.targetMouseX - this.mouseX) * 0.08;\r\n this.mouseY += (this.targetMouseY - this.mouseY) * 0.08;\r\n \r\n this.ctx.clearRect(0, 0, this.width, this.height);\r\n \r\n this.drawBackground(this.ctx);\r\n this.drawWaves(this.ctx);\r\n this.drawParticles(this.ctx);\r\n this.drawMouseGlow(this.ctx);\r\n \r\n if (this.isRunning) {\r\n requestAnimationFrame(() => this.animate());\r\n }\r\n }\r\n\r\n /**\r\n * Starts or resumes the animation loop and attaches interaction listeners.\r\n */\r\n start() {\r\n if (this.isRunning) {\r\n return;\r\n }\r\n \r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('mousemove', this._onMouseMove, {passive: true});\r\n window.addEventListener('touchmove', this._onTouchMove, {passive: false});\r\n window.addEventListener('touchend', this._onTouchEnd, {passive: true});\r\n window.addEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n \r\n this.isRunning = true;\r\n \r\n this.animate();\r\n }\r\n\r\n /**\r\n * Pauses the animation loop and detaches interaction listeners to save resources.\r\n */\r\n stop() {\r\n this.isRunning = false;\r\n \r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('mousemove', this._onMouseMove);\r\n window.removeEventListener('touchmove', this._onTouchMove);\r\n window.removeEventListener('touchend', this._onTouchEnd);\r\n window.removeEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n }\r\n\r\n /**\r\n * Stops the animation, removes event listeners, and cleans up any auto-injected DOM elements.\r\n */\r\n destroy() {\r\n this.stop();\r\n \r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('resize', this._onResize);\r\n }\r\n \r\n if (this.canvas && this.canvas.id === 'wave-particles-canvas' && this.canvas.parentNode) {\r\n this.canvas.parentNode.removeChild(this.canvas);\r\n }\r\n \r\n this.canvas = null;\r\n this.ctx = null;\r\n }\r\n}\r\n\r\nexport default WaveParticles;\r\n", "import WaveParticles from './index.js';\r\n\r\n/**\r\n * Browser-only entry point for IIFE / script-tag usage.\r\n * Exposes the WaveParticles class directly on the global object.\r\n */\r\nif (typeof window !== 'undefined') {\r\n window.WaveParticles = WaveParticles;\r\n} else if (typeof globalThis !== 'undefined') {\r\n globalThis.WaveParticles = WaveParticles;\r\n}\r\n"],
5
- "mappings": "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",
6
- "names": ["WaveParticles", "options", "providedCanvasOrSelector", "config", "resolvedCanvas", "rect", "ctx", "e", "userConfig", "defaults", "result", "key", "el", "body", "w", "h", "attrW", "attrH", "dpr", "countScale", "maxCount", "particleCount", "touch", "colors", "gradient", "c", "i", "mouseNormX", "mouseNormY", "wi", "wave", "numLayers", "layer", "layerOpacity", "baseY", "mouseEffect", "step", "x", "y", "dx", "dist", "baseColor", "m", "p", "currentOpacity", "dy", "force", "grad", "src_default", "src_default"]
4
+ "sourcesContent": ["/**\r\n * js-waves-particles\r\n * A canvas-based wave and particle animation library with mouse-reactive effects.\r\n * Developed by Luis 'PlatinumBlade' Moniz.\r\n */\r\n\r\nclass WaveParticles {\r\n /**\r\n * Initializes a new WaveParticles animation engine.\r\n *\r\n * @param {import('./index').WaveParticlesOptions} [options] - Configuration for the engine.\r\n * @param {HTMLCanvasElement|string} [options.canvas] - The target canvas element or a CSS selector (e.g., '#bg'). If omitted, a full-screen fixed canvas is automatically created.\r\n * @param {import('./index').WaveParticlesConfig} [options.config] - Visual parameters for waves, particles, and colors.\r\n */\r\n constructor(options = {}) {\r\n const { canvas: providedCanvasOrSelector, config } = options || {};\r\n\r\n // --- State ---\r\n this.canvas = null;\r\n this.ctx = null;\r\n this.mouseX = 0;\r\n this.mouseY = 0;\r\n this.targetMouseX = -1000;\r\n this.targetMouseY = -1000;\r\n this.mouseActive = false;\r\n this.width = 0;\r\n this.height = 0;\r\n this.config = this._mergeDefaults(config || {});\r\n this.time = 0;\r\n this.isRunning = false;\r\n this.particles = [];\r\n this._resizeTimeout = null;\r\n\r\n const resolvedCanvas = typeof document !== 'undefined' && providedCanvasOrSelector ? (() => {\r\n if (typeof providedCanvasOrSelector === 'string') {\r\n return /** @type {HTMLCanvasElement|null} */ (document.querySelector(providedCanvasOrSelector));\r\n }\r\n\r\n return /** @type {HTMLCanvasElement | null} */ (providedCanvasOrSelector);\r\n })() : null;\r\n\r\n if (resolvedCanvas) {\r\n this.canvas = resolvedCanvas;\r\n const rect = resolvedCanvas.getBoundingClientRect();\r\n this.width = Math.round(rect.width || window.innerWidth);\r\n this.height = Math.round(rect.height || window.innerHeight);\r\n } else {\r\n this._createAutoCanvas();\r\n }\r\n\r\n try {\r\n if (!this.canvas) {\r\n throw new Error('No canvas element available.');\r\n }\r\n\r\n const ctx = this.canvas.getContext('2d');\r\n\r\n if (!ctx) {\r\n throw new Error('Could not get 2D rendering context.');\r\n }\r\n\r\n this.ctx = ctx;\r\n } catch (e) {\r\n console.error('[WaveParticles] Canvas error:', e);\r\n return;\r\n }\r\n\r\n this._onMouseMove = this._onMouseMove.bind(this);\r\n this._onMouseLeave = this._onMouseLeave.bind(this);\r\n this._onTouchMove = this._onTouchMove.bind(this);\r\n this._onTouchEnd = this._onTouchEnd.bind(this);\r\n this._onResize = this._onResize.bind(this);\r\n\r\n if (typeof document !== 'undefined') {\r\n window.addEventListener('resize', this._onResize);\r\n this.resize(); // Initial size setup\r\n }\r\n\r\n this.initParticles();\r\n this.start();\r\n }\r\n\r\n /**\r\n * Internal method to merge user configuration with library defaults.\r\n * @private\r\n */\r\n _mergeDefaults(userConfig) {\r\n const defaults = {\r\n waves: [\r\n {\r\n amplitude: 60,\r\n frequency: 0.003,\r\n speed: 0.006,\r\n yOffset: 0.55,\r\n color: 'rgba(248, 225, 231, 0.25)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.45\r\n },\r\n {\r\n amplitude: 50,\r\n frequency: 0.004,\r\n speed: 0.008,\r\n yOffset: 0.60,\r\n color: 'rgba(212, 165, 165, 0.2)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.5\r\n },\r\n {\r\n amplitude: 70,\r\n frequency: 0.0025,\r\n speed: 0.005,\r\n yOffset: 0.65,\r\n color: 'rgba(255, 255, 255, 0.2)',\r\n lineWidth: 1.5,\r\n mouseInfluence: 0.4\r\n },\r\n {\r\n amplitude: 40,\r\n frequency: 0.0035,\r\n speed: 0.010,\r\n yOffset: 0.70,\r\n color: 'rgba(201, 169, 110, 0.12)',\r\n lineWidth: 1,\r\n mouseInfluence: 0.55\r\n }\r\n ],\r\n particles: { countScale: 8000, maxCount: 180 },\r\n colors: {\r\n backgroundGradient: ['#fdfcfb', '#f7ede2', '#e8d5d0'],\r\n particleColorPrefixes: [\r\n 'rgba(248, 225, 231,',\r\n 'rgba(212, 165, 165,',\r\n 'rgba(201, 169, 110,',\r\n 'rgba(255, 255, 255,',\r\n 'rgba(232, 213, 208,'\r\n ],\r\n mouseGlowStops: [\r\n { offset: 0, color: 'rgba(255, 255, 255, 0.08)' },\r\n { offset: 0.5, color: 'rgba(248, 225, 231, 0.04)' },\r\n { offset: 1, color: 'rgba(248, 225, 231, 0)' }\r\n ]\r\n }\r\n };\r\n\r\n const result = {};\r\n\r\n for (const key in defaults) {\r\n if (!defaults.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n if (!(userConfig && userConfig[key])) {\r\n result[key] = JSON.parse(JSON.stringify(defaults[key]));\r\n } else if (typeof defaults[key] === 'object' && !Array.isArray(defaults[key]) && typeof userConfig[key] === 'object') {\r\n result[key] = Object.assign({}, defaults[key], userConfig[key]);\r\n } else if (key === 'waves') {\r\n result.waves = Array.isArray(userConfig.waves) ? [...userConfig.waves] : JSON.parse(JSON.stringify(defaults.waves));\r\n } else {\r\n result[key] = userConfig[key];\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Automatically creates and injects a canvas element into the DOM if none was provided.\r\n * @private\r\n */\r\n _createAutoCanvas() {\r\n if (typeof document === 'undefined') {\r\n return;\r\n }\r\n\r\n const el = document.createElement('canvas');\r\n\r\n el.id = 'wave-particles-canvas';\r\n\r\n Object.assign(el.style, {\r\n position: 'fixed',\r\n top: '0',\r\n left: '0',\r\n width: '100%',\r\n height: '100%',\r\n zIndex: '-1',\r\n pointerEvents: 'none'\r\n });\r\n\r\n const body = document.body;\r\n\r\n if (!body) {\r\n return;\r\n }\r\n\r\n body.insertBefore(el, body.firstChild);\r\n this.canvas = el;\r\n this.width = window.innerWidth;\r\n this.height = window.innerHeight;\r\n }\r\n\r\n /**\r\n * Event handler for window resize events, including debouncing to prevent performance issues.\r\n * @private\r\n */\r\n _onResize() {\r\n if (this._resizeTimeout) clearTimeout(this._resizeTimeout);\r\n // Debounce resize to prevent flashing and high CPU usage\r\n this._resizeTimeout = setTimeout(() => {\r\n this.resize();\r\n }, 250);\r\n }\r\n\r\n /**\r\n * Recalculates canvas dimensions based on its display size and Device Pixel Ratio.\r\n * Re-initializes particles to match the new surface area.\r\n */\r\n resize() {\r\n if (!this.canvas) {\r\n return;\r\n }\r\n\r\n const rect = this.canvas.getBoundingClientRect();\r\n const dpr = window.devicePixelRatio || 1;\r\n\r\n // Use CSS pixels for logical dimensions.\r\n // Fallback to window size if canvas is not in layout (prevents the \"multiplication\" bug).\r\n const w = rect.width || window.innerWidth;\r\n const h = rect.height || window.innerHeight;\r\n\r\n this.width = w;\r\n this.height = h;\r\n\r\n // Set physical pixels for the canvas buffer\r\n this.canvas.width = Math.round(w * dpr);\r\n this.canvas.height = Math.round(h * dpr);\r\n\r\n // Scale the context to ensure all drawing operations use CSS pixels.\r\n // Re-get context if it was lost or not yet initialized.\r\n if (!this.ctx) {\r\n this.ctx = this.canvas.getContext('2d');\r\n }\r\n\r\n if (this.ctx) {\r\n this.ctx.scale(dpr, dpr);\r\n }\r\n\r\n if (this.isRunning) {\r\n this.initParticles();\r\n }\r\n }\r\n\r\n /**\r\n * Generates a new set of particles based on the current canvas area and configuration.\r\n */\r\n initParticles() {\r\n const { countScale = 8000, maxCount = 180 } = this.config.particles;\r\n\r\n const particleCount = Math.min(Math.floor((this.width * this.height) / (countScale > 0 ? countScale : 8000)), maxCount);\r\n\r\n this.particles = Array.from({ length: particleCount }, () => ({\r\n x: Math.random() * this.width,\r\n y: Math.random() * this.height,\r\n size: Math.random() * 4 + 1.5,\r\n speedX: (Math.random() - 0.5) * 0.4,\r\n speedY: (Math.random() - 0.5) * 0.4,\r\n opacity: Math.random() * 0.6 + 0.3,\r\n pulse: Math.random() * Math.PI * 2,\r\n pulseSpeed: Math.random() * 0.025 + 0.01,\r\n colorPrefix: this.config.colors.particleColorPrefixes[Math.floor(Math.random() * this.config.colors.particleColorPrefixes.length)]\r\n }));\r\n }\r\n\r\n _onMouseMove(e) {\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n if (!rect) {\r\n return;\r\n }\r\n\r\n // Calculate position relative to the canvas in CSS pixels\r\n this.targetMouseX = e.clientX - rect.left;\r\n this.targetMouseY = e.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onMouseLeave() {\r\n this.mouseActive = false;\r\n }\r\n\r\n _onTouchMove(e) {\r\n const touch = e.touches[0];\r\n const rect = this.canvas.getBoundingClientRect();\r\n\r\n if (!touch || !rect) {\r\n return;\r\n }\r\n\r\n this.targetMouseX = touch.clientX - rect.left;\r\n this.targetMouseY = touch.clientY - rect.top;\r\n this.mouseActive = true;\r\n }\r\n\r\n _onTouchEnd() {\r\n this.mouseActive = false;\r\n }\r\n\r\n /**\r\n * Renders the radial gradient background across the entire canvas.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawBackground(ctx) {\r\n const colors = this.config.colors.backgroundGradient;\r\n\r\n const gradient = ctx.createRadialGradient(this.width / 2, this.height / 2, 0, this.width / 2, this.height / 2, Math.max(this.width, this.height) * 0.8);\r\n\r\n colors.forEach((c, i) => gradient.addColorStop(i / (colors.length - 1 || 1), c));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fillRect(0, 0, this.width, this.height);\r\n }\r\n\r\n /**\r\n * Renders all wave layers, accounting for mouse interaction and layer offsets.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawWaves(ctx) {\r\n const mouseNormX = this.mouseActive ? this.mouseX / this.width : -1;\r\n const mouseNormY = this.mouseActive ? this.mouseY / this.height : -1;\r\n\r\n for (let wi = 0; wi < this.config.waves.length; wi++) {\r\n const wave = this.config.waves[wi];\r\n const numLayers = Math.max(2, wave.layers || 2);\r\n\r\n for (let layer = 0; layer < numLayers; layer++) {\r\n const layerOpacity = (1 - layer / numLayers) * 0.5 + 0.5;\r\n\r\n ctx.beginPath();\r\n\r\n const baseY = this.height * wave.yOffset + layer * 3;\r\n\r\n const mouseEffect = this.mouseActive ? (mouseNormX - 0.5) * (wave.mouseInfluence || 0.45) * 150 : 0;\r\n\r\n ctx.moveTo(0, this.height);\r\n\r\n const step = Math.max(2, Math.floor(this.width / 480));\r\n\r\n for (let x = 0; x <= this.width; x += step) {\r\n let y = baseY;\r\n\r\n y += Math.sin(x * wave.frequency + this.time * wave.speed + layer * 0.1) * wave.amplitude;\r\n y += Math.sin(x * wave.frequency * 1.5 + this.time * wave.speed * 0.7 + wi) * wave.amplitude * 0.3;\r\n\r\n if (this.mouseActive) {\r\n const dx = x - this.mouseX;\r\n const dist = Math.abs(dx) / this.width;\r\n y += Math.sin(dist * Math.PI) * (mouseNormY > 0 ? (this.mouseY - this.height / 2) : 0) * 0.1 * (wave.mouseInfluence || 0.45);\r\n }\r\n\r\n y += mouseEffect * Math.sin((x / this.width) * Math.PI);\r\n\r\n ctx.lineTo(x, y);\r\n }\r\n\r\n ctx.lineTo(this.width, this.height);\r\n\r\n ctx.closePath();\r\n\r\n const baseColor = wave.color || 'rgba(139, 114, 86, 0.25)';\r\n\r\n ctx.fillStyle = baseColor.replace(/([\\d.]+)\\)$/, (m) => `${parseFloat(m) * layerOpacity})`);\r\n\r\n if (wave.lineWidth != null) {\r\n ctx.lineWidth = wave.lineWidth;\r\n }\r\n\r\n ctx.fill();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates and renders the particle system, including movement and mouse repulsion logic.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawParticles(ctx) {\r\n const maxDist = 150;\r\n\r\n for (const p of this.particles) {\r\n p.pulse += p.pulseSpeed;\r\n\r\n const currentOpacity = p.opacity * (Math.sin(p.pulse) * 0.3 + 0.7);\r\n\r\n if (this.mouseActive) {\r\n const dx = p.x - this.mouseX, dy = p.y - this.mouseY, dist = Math.sqrt(dx * dx + dy * dy);\r\n\r\n if (dist < maxDist && dist > 0.1) {\r\n const force = (1 - dist / maxDist) * 2;\r\n p.x += (dx / dist) * force;\r\n p.y += (dy / dist) * force;\r\n }\r\n }\r\n\r\n p.x += p.speedX;\r\n p.y += p.speedY;\r\n\r\n if (p.x < 0) {\r\n p.x = this.width;\r\n }\r\n\r\n if (p.x > this.width) {\r\n p.x = 0;\r\n }\r\n\r\n if (p.y < 0) {\r\n p.y = this.height;\r\n }\r\n\r\n if (p.y > this.height) {\r\n p.y = 0;\r\n }\r\n\r\n const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 2);\r\n\r\n grad.addColorStop(0, p.colorPrefix + currentOpacity + ')');\r\n\r\n grad.addColorStop(1, p.colorPrefix + '0)');\r\n\r\n ctx.beginPath();\r\n\r\n ctx.fillStyle = grad;\r\n\r\n ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2);\r\n\r\n ctx.fill();\r\n\r\n ctx.beginPath();\r\n\r\n ctx.fillStyle = p.colorPrefix + (currentOpacity * 0.8) + ')';\r\n\r\n ctx.arc(p.x, p.y, p.size * 0.5, 0, Math.PI * 2);\r\n\r\n ctx.fill();\r\n }\r\n }\r\n\r\n /**\r\n * Renders a soft glow effect centered at the current mouse position.\r\n * @param {CanvasRenderingContext2D} ctx\r\n */\r\n drawMouseGlow(ctx) {\r\n if (!this.mouseActive) {\r\n return;\r\n }\r\n\r\n const gradient = ctx.createRadialGradient(this.mouseX, this.mouseY, 0, this.mouseX, this.mouseY, 200);\r\n\r\n const stops = this.config.colors.mouseGlowStops;\r\n\r\n stops.forEach((s) => gradient.addColorStop(s.offset, s.color));\r\n\r\n ctx.beginPath();\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.arc(this.mouseX, this.mouseY, 200, 0, Math.PI * 2);\r\n\r\n ctx.fill();\r\n }\r\n\r\n /**\r\n * The main animation loop. Updates state and draws the next frame.\r\n */\r\n animate() {\r\n if (!this.ctx) {\r\n return;\r\n }\r\n\r\n this.time += 1;\r\n\r\n this.mouseX += (this.targetMouseX - this.mouseX) * 0.08;\r\n this.mouseY += (this.targetMouseY - this.mouseY) * 0.08;\r\n\r\n this.ctx.clearRect(0, 0, this.width, this.height);\r\n\r\n this.drawBackground(this.ctx);\r\n this.drawWaves(this.ctx);\r\n this.drawParticles(this.ctx);\r\n this.drawMouseGlow(this.ctx);\r\n\r\n if (this.isRunning) {\r\n requestAnimationFrame(() => this.animate());\r\n }\r\n }\r\n\r\n /**\r\n * Starts or resumes the animation loop and attaches interaction listeners.\r\n */\r\n start() {\r\n if (this.isRunning) {\r\n return;\r\n }\r\n\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('mousemove', this._onMouseMove, { passive: true });\r\n window.addEventListener('touchmove', this._onTouchMove, { passive: false });\r\n window.addEventListener('touchend', this._onTouchEnd, { passive: true });\r\n window.addEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n\r\n this.isRunning = true;\r\n\r\n this.animate();\r\n }\r\n\r\n /**\r\n * Pauses the animation loop and detaches interaction listeners to save resources.\r\n */\r\n stop() {\r\n this.isRunning = false;\r\n\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('mousemove', this._onMouseMove);\r\n window.removeEventListener('touchmove', this._onTouchMove);\r\n window.removeEventListener('touchend', this._onTouchEnd);\r\n window.removeEventListener('mouseleave', this._onMouseLeave);\r\n }\r\n }\r\n\r\n /**\r\n * Stops the animation, removes event listeners, and cleans up any auto-injected DOM elements.\r\n */\r\n destroy() {\r\n this.stop();\r\n\r\n if (typeof window !== 'undefined') {\r\n window.removeEventListener('resize', this._onResize);\r\n }\r\n\r\n if (this.canvas && this.canvas.id === 'wave-particles-canvas' && this.canvas.parentNode) {\r\n this.canvas.parentNode.removeChild(this.canvas);\r\n }\r\n\r\n this.canvas = null;\r\n this.ctx = null;\r\n }\r\n}\r\n\r\nexport default WaveParticles;\r\n", "import WaveParticles from './index.js';\r\n\r\n/**\r\n * Browser-only entry point for IIFE / script-tag usage.\r\n * Exposes the WaveParticles class directly on the global object.\r\n */\r\nif (typeof window !== 'undefined') {\r\n window.WaveParticles = WaveParticles;\r\n} else if (typeof globalThis !== 'undefined') {\r\n globalThis.WaveParticles = WaveParticles;\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["WaveParticles", "options", "providedCanvasOrSelector", "config", "resolvedCanvas", "rect", "ctx", "e", "userConfig", "defaults", "result", "key", "el", "body", "dpr", "w", "h", "countScale", "maxCount", "particleCount", "touch", "colors", "gradient", "c", "i", "mouseNormX", "mouseNormY", "wi", "wave", "numLayers", "layer", "layerOpacity", "baseY", "mouseEffect", "step", "x", "y", "dx", "dist", "baseColor", "m", "p", "currentOpacity", "dy", "force", "grad", "src_default", "src_default"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-waves-particles",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A lightweight, canvas-based wave and particle animation library with mouse-reactive effects. Perfect for adding a subtle, organic feel to backgrounds in web projects.",
5
5
  "type": "module",
6
6
  "main": "./dist/wave-particles.iife.js",
package/src/index.js CHANGED
@@ -13,7 +13,7 @@ class WaveParticles {
13
13
  * @param {import('./index').WaveParticlesConfig} [options.config] - Visual parameters for waves, particles, and colors.
14
14
  */
15
15
  constructor(options = {}) {
16
- const {canvas: providedCanvasOrSelector, config} = options || {};
16
+ const { canvas: providedCanvasOrSelector, config } = options || {};
17
17
 
18
18
  // --- State ---
19
19
  this.canvas = null;
@@ -124,7 +124,7 @@ class WaveParticles {
124
124
  mouseInfluence: 0.55
125
125
  }
126
126
  ],
127
- particles: {countScale: 8000, maxCount: 180},
127
+ particles: { countScale: 8000, maxCount: 180 },
128
128
  colors: {
129
129
  backgroundGradient: ['#fdfcfb', '#f7ede2', '#e8d5d0'],
130
130
  particleColorPrefixes: [
@@ -135,9 +135,9 @@ class WaveParticles {
135
135
  'rgba(232, 213, 208,'
136
136
  ],
137
137
  mouseGlowStops: [
138
- {offset: 0, color: 'rgba(255, 255, 255, 0.08)'},
139
- {offset: 0.5, color: 'rgba(248, 225, 231, 0.04)'},
140
- {offset: 1, color: 'rgba(248, 225, 231, 0)'}
138
+ { offset: 0, color: 'rgba(255, 255, 255, 0.08)' },
139
+ { offset: 0.5, color: 'rgba(248, 225, 231, 0.04)' },
140
+ { offset: 1, color: 'rgba(248, 225, 231, 0)' }
141
141
  ]
142
142
  }
143
143
  };
@@ -159,7 +159,7 @@ class WaveParticles {
159
159
  result[key] = userConfig[key];
160
160
  }
161
161
  }
162
-
162
+
163
163
  return result;
164
164
  }
165
165
 
@@ -220,33 +220,31 @@ class WaveParticles {
220
220
  }
221
221
 
222
222
  const rect = this.canvas.getBoundingClientRect();
223
+ const dpr = window.devicePixelRatio || 1;
223
224
 
224
- let w, h;
225
-
226
- const attrW = parseInt(this.canvas.getAttribute('width'), 10);
227
- const attrH = parseInt(this.canvas.getAttribute('height'), 10);
228
-
229
- if (attrW && attrH) {
230
- w = Math.round(rect.width || attrW);
231
- h = Math.round(rect.height || attrH);
232
- } else {
233
- w = window.innerWidth;
234
- h = window.innerHeight;
225
+ // Use CSS pixels for logical dimensions.
226
+ // Fallback to window size if canvas is not in layout (prevents the "multiplication" bug).
227
+ const w = rect.width || window.innerWidth;
228
+ const h = rect.height || window.innerHeight;
235
229
 
236
- if (!this.canvas.parentNode && document.body) {
237
- document.body.insertBefore(this.canvas, document.body.firstChild);
238
- }
239
- }
240
-
241
230
  this.width = w;
242
231
  this.height = h;
243
232
 
244
- const dpr = window.devicePixelRatio || 1;
245
-
233
+ // Set physical pixels for the canvas buffer
246
234
  this.canvas.width = Math.round(w * dpr);
247
235
  this.canvas.height = Math.round(h * dpr);
248
236
 
249
- if (this.ctx && this.isRunning) {
237
+ // Scale the context to ensure all drawing operations use CSS pixels.
238
+ // Re-get context if it was lost or not yet initialized.
239
+ if (!this.ctx) {
240
+ this.ctx = this.canvas.getContext('2d');
241
+ }
242
+
243
+ if (this.ctx) {
244
+ this.ctx.scale(dpr, dpr);
245
+ }
246
+
247
+ if (this.isRunning) {
250
248
  this.initParticles();
251
249
  }
252
250
  }
@@ -255,11 +253,11 @@ class WaveParticles {
255
253
  * Generates a new set of particles based on the current canvas area and configuration.
256
254
  */
257
255
  initParticles() {
258
- const {countScale = 8000, maxCount = 180} = this.config.particles;
256
+ const { countScale = 8000, maxCount = 180 } = this.config.particles;
259
257
 
260
258
  const particleCount = Math.min(Math.floor((this.width * this.height) / (countScale > 0 ? countScale : 8000)), maxCount);
261
259
 
262
- this.particles = Array.from({length: particleCount}, () => ({
260
+ this.particles = Array.from({ length: particleCount }, () => ({
263
261
  x: Math.random() * this.width,
264
262
  y: Math.random() * this.height,
265
263
  size: Math.random() * 4 + 1.5,
@@ -274,7 +272,7 @@ class WaveParticles {
274
272
 
275
273
  _onMouseMove(e) {
276
274
  const rect = this.canvas.getBoundingClientRect();
277
-
275
+
278
276
  if (!rect) {
279
277
  return;
280
278
  }
@@ -292,7 +290,7 @@ class WaveParticles {
292
290
  _onTouchMove(e) {
293
291
  const touch = e.touches[0];
294
292
  const rect = this.canvas.getBoundingClientRect();
295
-
293
+
296
294
  if (!touch || !rect) {
297
295
  return;
298
296
  }
@@ -312,13 +310,13 @@ class WaveParticles {
312
310
  */
313
311
  drawBackground(ctx) {
314
312
  const colors = this.config.colors.backgroundGradient;
315
-
313
+
316
314
  const gradient = ctx.createRadialGradient(this.width / 2, this.height / 2, 0, this.width / 2, this.height / 2, Math.max(this.width, this.height) * 0.8);
317
-
315
+
318
316
  colors.forEach((c, i) => gradient.addColorStop(i / (colors.length - 1 || 1), c));
319
-
317
+
320
318
  ctx.fillStyle = gradient;
321
-
319
+
322
320
  ctx.fillRect(0, 0, this.width, this.height);
323
321
  }
324
322
 
@@ -336,46 +334,46 @@ class WaveParticles {
336
334
 
337
335
  for (let layer = 0; layer < numLayers; layer++) {
338
336
  const layerOpacity = (1 - layer / numLayers) * 0.5 + 0.5;
339
-
337
+
340
338
  ctx.beginPath();
341
-
339
+
342
340
  const baseY = this.height * wave.yOffset + layer * 3;
343
-
341
+
344
342
  const mouseEffect = this.mouseActive ? (mouseNormX - 0.5) * (wave.mouseInfluence || 0.45) * 150 : 0;
345
-
343
+
346
344
  ctx.moveTo(0, this.height);
347
345
 
348
346
  const step = Math.max(2, Math.floor(this.width / 480));
349
-
347
+
350
348
  for (let x = 0; x <= this.width; x += step) {
351
349
  let y = baseY;
352
-
350
+
353
351
  y += Math.sin(x * wave.frequency + this.time * wave.speed + layer * 0.1) * wave.amplitude;
354
352
  y += Math.sin(x * wave.frequency * 1.5 + this.time * wave.speed * 0.7 + wi) * wave.amplitude * 0.3;
355
-
353
+
356
354
  if (this.mouseActive) {
357
355
  const dx = x - this.mouseX;
358
356
  const dist = Math.abs(dx) / this.width;
359
357
  y += Math.sin(dist * Math.PI) * (mouseNormY > 0 ? (this.mouseY - this.height / 2) : 0) * 0.1 * (wave.mouseInfluence || 0.45);
360
358
  }
361
-
359
+
362
360
  y += mouseEffect * Math.sin((x / this.width) * Math.PI);
363
-
361
+
364
362
  ctx.lineTo(x, y);
365
363
  }
366
-
364
+
367
365
  ctx.lineTo(this.width, this.height);
368
-
366
+
369
367
  ctx.closePath();
370
-
368
+
371
369
  const baseColor = wave.color || 'rgba(139, 114, 86, 0.25)';
372
-
370
+
373
371
  ctx.fillStyle = baseColor.replace(/([\d.]+)\)$/, (m) => `${parseFloat(m) * layerOpacity})`);
374
-
372
+
375
373
  if (wave.lineWidth != null) {
376
374
  ctx.lineWidth = wave.lineWidth;
377
375
  }
378
-
376
+
379
377
  ctx.fill();
380
378
  }
381
379
  }
@@ -387,61 +385,61 @@ class WaveParticles {
387
385
  */
388
386
  drawParticles(ctx) {
389
387
  const maxDist = 150;
390
-
388
+
391
389
  for (const p of this.particles) {
392
390
  p.pulse += p.pulseSpeed;
393
-
391
+
394
392
  const currentOpacity = p.opacity * (Math.sin(p.pulse) * 0.3 + 0.7);
395
-
393
+
396
394
  if (this.mouseActive) {
397
395
  const dx = p.x - this.mouseX, dy = p.y - this.mouseY, dist = Math.sqrt(dx * dx + dy * dy);
398
-
396
+
399
397
  if (dist < maxDist && dist > 0.1) {
400
398
  const force = (1 - dist / maxDist) * 2;
401
399
  p.x += (dx / dist) * force;
402
400
  p.y += (dy / dist) * force;
403
401
  }
404
402
  }
405
-
403
+
406
404
  p.x += p.speedX;
407
405
  p.y += p.speedY;
408
-
406
+
409
407
  if (p.x < 0) {
410
408
  p.x = this.width;
411
409
  }
412
-
410
+
413
411
  if (p.x > this.width) {
414
412
  p.x = 0;
415
413
  }
416
-
414
+
417
415
  if (p.y < 0) {
418
416
  p.y = this.height;
419
417
  }
420
-
418
+
421
419
  if (p.y > this.height) {
422
420
  p.y = 0;
423
421
  }
424
422
 
425
423
  const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size * 2);
426
-
424
+
427
425
  grad.addColorStop(0, p.colorPrefix + currentOpacity + ')');
428
-
426
+
429
427
  grad.addColorStop(1, p.colorPrefix + '0)');
430
-
428
+
431
429
  ctx.beginPath();
432
-
430
+
433
431
  ctx.fillStyle = grad;
434
-
432
+
435
433
  ctx.arc(p.x, p.y, p.size * 2, 0, Math.PI * 2);
436
-
434
+
437
435
  ctx.fill();
438
-
436
+
439
437
  ctx.beginPath();
440
-
438
+
441
439
  ctx.fillStyle = p.colorPrefix + (currentOpacity * 0.8) + ')';
442
-
440
+
443
441
  ctx.arc(p.x, p.y, p.size * 0.5, 0, Math.PI * 2);
444
-
442
+
445
443
  ctx.fill();
446
444
  }
447
445
  }
@@ -454,19 +452,19 @@ class WaveParticles {
454
452
  if (!this.mouseActive) {
455
453
  return;
456
454
  }
457
-
455
+
458
456
  const gradient = ctx.createRadialGradient(this.mouseX, this.mouseY, 0, this.mouseX, this.mouseY, 200);
459
-
457
+
460
458
  const stops = this.config.colors.mouseGlowStops;
461
-
459
+
462
460
  stops.forEach((s) => gradient.addColorStop(s.offset, s.color));
463
-
461
+
464
462
  ctx.beginPath();
465
-
463
+
466
464
  ctx.fillStyle = gradient;
467
-
465
+
468
466
  ctx.arc(this.mouseX, this.mouseY, 200, 0, Math.PI * 2);
469
-
467
+
470
468
  ctx.fill();
471
469
  }
472
470
 
@@ -477,19 +475,19 @@ class WaveParticles {
477
475
  if (!this.ctx) {
478
476
  return;
479
477
  }
480
-
478
+
481
479
  this.time += 1;
482
-
480
+
483
481
  this.mouseX += (this.targetMouseX - this.mouseX) * 0.08;
484
482
  this.mouseY += (this.targetMouseY - this.mouseY) * 0.08;
485
-
483
+
486
484
  this.ctx.clearRect(0, 0, this.width, this.height);
487
-
485
+
488
486
  this.drawBackground(this.ctx);
489
487
  this.drawWaves(this.ctx);
490
488
  this.drawParticles(this.ctx);
491
489
  this.drawMouseGlow(this.ctx);
492
-
490
+
493
491
  if (this.isRunning) {
494
492
  requestAnimationFrame(() => this.animate());
495
493
  }
@@ -502,16 +500,16 @@ class WaveParticles {
502
500
  if (this.isRunning) {
503
501
  return;
504
502
  }
505
-
503
+
506
504
  if (typeof window !== 'undefined') {
507
- window.addEventListener('mousemove', this._onMouseMove, {passive: true});
508
- window.addEventListener('touchmove', this._onTouchMove, {passive: false});
509
- window.addEventListener('touchend', this._onTouchEnd, {passive: true});
505
+ window.addEventListener('mousemove', this._onMouseMove, { passive: true });
506
+ window.addEventListener('touchmove', this._onTouchMove, { passive: false });
507
+ window.addEventListener('touchend', this._onTouchEnd, { passive: true });
510
508
  window.addEventListener('mouseleave', this._onMouseLeave);
511
509
  }
512
-
510
+
513
511
  this.isRunning = true;
514
-
512
+
515
513
  this.animate();
516
514
  }
517
515
 
@@ -520,7 +518,7 @@ class WaveParticles {
520
518
  */
521
519
  stop() {
522
520
  this.isRunning = false;
523
-
521
+
524
522
  if (typeof window !== 'undefined') {
525
523
  window.removeEventListener('mousemove', this._onMouseMove);
526
524
  window.removeEventListener('touchmove', this._onTouchMove);
@@ -534,15 +532,15 @@ class WaveParticles {
534
532
  */
535
533
  destroy() {
536
534
  this.stop();
537
-
535
+
538
536
  if (typeof window !== 'undefined') {
539
537
  window.removeEventListener('resize', this._onResize);
540
538
  }
541
-
539
+
542
540
  if (this.canvas && this.canvas.id === 'wave-particles-canvas' && this.canvas.parentNode) {
543
541
  this.canvas.parentNode.removeChild(this.canvas);
544
542
  }
545
-
543
+
546
544
  this.canvas = null;
547
545
  this.ctx = null;
548
546
  }