particle-canvas-pro 1.4.4 → 1.4.6

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.
package/README.md CHANGED
@@ -101,7 +101,7 @@ particleSystem.start();
101
101
  | 方法名 | 说明 |
102
102
  |-----------|--------------------------------------|
103
103
  | start() | 启动粒子动画 |
104
- | pause() | 暂停粒子动画 |
104
+ | stop() | 暂停粒子动画 |
105
105
  | reset() | 重置粒子位置和状态,重新启动动画 |
106
106
  | destroy() | 销毁粒子动画,移除画布元素 |
107
107
 
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});class i{constructor(i={}){this.MAX_PARTICLE_NUMBER=800,this.MAX_PARTICLE_SPEED=3,this.MAX_PARTICLE_SIZE=10,this.MAX_LINK_DISTANCE=300,this.MAX_LINE_WIDTH=5,this.MAX_LINE_OPACITY=1,this.MAX_TRAIL_VALUE=1,this.MAX_PARTICLE_BLUR=5,this.MAX_TRAIL_INTENSITY=5;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgb(10, 10, 25)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",particleBlur:void 0!==t.particleBlur?t.particleBlur:2,lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLine:void 0===t.showLine||t.showLine,canvasSize:t.canvasSize||[800,600],showTrail:void 0===t.showTrail||t.showTrail,trailIntensity:t.trailIntensity||2},this.particles=[],this.animationId=null,this.isRunning=!1,this.lastTime=0,this.fps=60,this.fpsInterval=1e3/60,this.then=Date.now(),this.frameCount=0,this.lastFpsUpdate=Date.now(),this.resizeTimer=null,this.wasRunningBeforeHide=!1,this.lastFrameTime=performance.now(),this.init()}validateAndLimitOptions(i){const t=Object.assign({},i);return void 0!==i.particleNumber&&(i.particleNumber>this.MAX_PARTICLE_NUMBER?(console.warn(`Warning: particleNumber (${i.particleNumber}) exceeds maximum allowed value (${this.MAX_PARTICLE_NUMBER}). Using maximum value instead.`),t.particleNumber=this.MAX_PARTICLE_NUMBER):i.particleNumber<1&&(console.warn(`Warning: particleNumber (${i.particleNumber}) is below minimum value (1). Using default value instead.`),t.particleNumber=150)),void 0!==i.particleSpeed&&(i.particleSpeed>this.MAX_PARTICLE_SPEED?(console.warn(`Warning: particleSpeed (${i.particleSpeed}) exceeds maximum allowed value (${this.MAX_PARTICLE_SPEED}). Using maximum value instead.`),t.particleSpeed=this.MAX_PARTICLE_SPEED):i.particleSpeed<0&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0). Using default value instead.`),t.particleSpeed=1)),void 0!==i.particleSize&&(i.particleSize>this.MAX_PARTICLE_SIZE?(console.warn(`Warning: particleSize (${i.particleSize}) exceeds maximum allowed value (${this.MAX_PARTICLE_SIZE}). Using maximum value instead.`),t.particleSize=this.MAX_PARTICLE_SIZE):i.particleSize<1&&(console.warn(`Warning: particleSize (${i.particleSize}) is below minimum value (1). Using default value instead.`),t.particleSize=3)),void 0!==i.particleBlur&&(i.particleBlur>this.MAX_PARTICLE_BLUR?(console.warn(`Warning: particleBlur (${i.particleBlur}) exceeds maximum allowed value (${this.MAX_PARTICLE_BLUR}). Using maximum value instead.`),t.particleBlur=this.MAX_PARTICLE_BLUR):i.particleBlur<0&&(console.warn(`Warning: particleBlur (${i.particleBlur}) is below minimum value (0). Using default value instead.`),t.particleBlur=2)),void 0!==i.linkDistance&&(i.linkDistance>this.MAX_LINK_DISTANCE?(console.warn(`Warning: linkDistance (${i.linkDistance}) exceeds maximum allowed value (${this.MAX_LINK_DISTANCE}). Using maximum value instead.`),t.linkDistance=this.MAX_LINK_DISTANCE):i.linkDistance<10&&(console.warn(`Warning: linkDistance (${i.linkDistance}) is below minimum value (10). Using default value instead.`),t.linkDistance=120)),void 0!==i.lineWidth&&(i.lineWidth>this.MAX_LINE_WIDTH?(console.warn(`Warning: lineWidth (${i.lineWidth}) exceeds maximum allowed value (${this.MAX_LINE_WIDTH}). Using maximum value instead.`),t.lineWidth=this.MAX_LINE_WIDTH):i.lineWidth<0&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0). Using default value instead.`),t.lineWidth=1)),void 0!==i.lineOpacity&&(i.lineOpacity>this.MAX_LINE_OPACITY?(console.warn(`Warning: lineOpacity (${i.lineOpacity}) exceeds maximum allowed value (${this.MAX_LINE_OPACITY}). Using maximum value instead.`),t.lineOpacity=this.MAX_LINE_OPACITY):i.lineOpacity<0&&(console.warn(`Warning: lineOpacity (${i.lineOpacity}) is below minimum value (0). Using default value instead.`),t.lineOpacity=.3)),void 0!==i.trailIntensity&&(i.trailIntensity>this.MAX_TRAIL_INTENSITY?(console.warn(`Warning: trailIntensity (${i.trailIntensity}) exceeds maximum allowed value (${this.MAX_TRAIL_INTENSITY}). Using maximum value instead.`),t.trailIntensity=this.MAX_TRAIL_INTENSITY):i.trailIntensity<1&&(console.warn(`Warning: trailIntensity (${i.trailIntensity}) is below minimum value (1). Using default value instead.`),t.trailIntensity=2)),t}init(){this.canvas=document.createElement("canvas");const i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");if(this.ctx=i,"string"==typeof this.config.canvasContainer){const i=document.querySelector(this.config.canvasContainer);if(!i)throw new Error(`Canvas container not found: ${this.config.canvasContainer}`);this.container=i}else this.container=this.config.canvasContainer;this.container?(this.container.appendChild(this.canvas),this.setupCanvas(),this.createParticles(),this.bindEvents()):console.error("Canvas container not found")}setupCanvas(){if(this.config.isBackground)this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.zIndex="-1",this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;else{this.canvas.style.display="block";const[i,t]=this.config.canvasSize;this.canvas.width=i,this.canvas.height=t,this.canvas.style.width=i+"px",this.canvas.style.height=t+"px"}this.canvas.style.pointerEvents="none"}createParticles(){this.particles=[];const i=Array.isArray(this.config.particleColor);for(let t=0;t<this.config.particleNumber;t++){let t;if(i){const i=this.config.particleColor;t=i[Math.floor(Math.random()*i.length)]}else t=this.config.particleColor;this.particles.push({x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:2*(Math.random()-.5)*this.config.particleSpeed,vy:2*(Math.random()-.5)*this.config.particleSpeed,size:this.config.particleSize,color:t,originalColor:t,pulse:0,pulseSpeed:.05*Math.random()+.02,trailPositions:[]})}}updateParticles(i){const t=i/16.67;for(const i of this.particles)i.pulse+=i.pulseSpeed*t,i.pulse>2*Math.PI&&(i.pulse=0),this.config.showTrail&&(i.trailPositions.unshift({x:i.x,y:i.y}),i.trailPositions.length>10*this.config.trailIntensity&&(i.trailPositions.length=10*this.config.trailIntensity)),i.x+=i.vx*t,i.y+=i.vy*t,(i.x<0||i.x>this.canvas.width)&&(i.vx*=-1),(i.y<0||i.y>this.canvas.height)&&(i.vy*=-1),i.x=Math.max(0,Math.min(this.canvas.width,i.x)),i.y=Math.max(0,Math.min(this.canvas.height,i.y))}drawTrailEffect(){if(this.config.showTrail){this.ctx.save();for(const i of this.particles){if(i.trailPositions.length<2)continue;this.ctx.beginPath(),this.ctx.moveTo(i.trailPositions[0].x,i.trailPositions[0].y);for(let t=1;t<i.trailPositions.length;t++)this.ctx.lineTo(i.trailPositions[t].x,i.trailPositions[t].y);const t=1.2*i.size;this.ctx.lineWidth=t,this.ctx.lineCap="round",this.ctx.lineJoin="round";const s=i.trailPositions[0],e=i.trailPositions[i.trailPositions.length-1],a=this.ctx.createLinearGradient(s.x,s.y,e.x,e.y),n=this.parseColor(i.color),r=.35;a.addColorStop(0,`rgba(${n.r}, ${n.g}, ${n.b}, ${r})`),a.addColorStop(.3,`rgba(${n.r}, ${n.g}, ${n.b}, ${.6*r})`),a.addColorStop(.7,`rgba(${n.r}, ${n.g}, ${n.b}, ${.2*r})`),a.addColorStop(1,`rgba(${n.r}, ${n.g}, ${n.b}, 0)`),this.ctx.strokeStyle=a,this.ctx.stroke()}this.ctx.restore()}}parseColor(i){if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3]),a:parseFloat(t[4])}}else if(i.startsWith("rgb")){const t=i.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3])}}else if(i.startsWith("#")){let t,s,e,a=i.replace("#","");if(3===a.length)t=parseInt(a[0]+a[0],16),s=parseInt(a[1]+a[1],16),e=parseInt(a[2]+a[2],16);else{if(6!==a.length)return{r:255,g:255,b:255};t=parseInt(a.substring(0,2),16),s=parseInt(a.substring(2,4),16),e=parseInt(a.substring(4,6),16)}return{r:t,g:s,b:e}}return{r:255,g:255,b:255}}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);let i=this.config.canvasBackgroundColor;if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t){const s=t[1],e=t[2],a=t[3];parseFloat(t[4])<1&&(i=`rgb(${s}, ${e}, ${a})`)}}if(this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.drawTrailEffect(),this.config.showLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const s=this.particles[i].x-this.particles[t].x,e=this.particles[i].y-this.particles[t].y,a=Math.sqrt(s*s+e*e);if(a<this.config.linkDistance){const s=this.config.lineOpacity*(1-a/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=s,this.ctx.lineWidth=this.config.lineWidth,this.ctx.beginPath(),this.ctx.moveTo(this.particles[i].x,this.particles[i].y),this.ctx.lineTo(this.particles[t].x,this.particles[t].y),this.ctx.stroke()}}this.ctx.globalAlpha=1;for(const i of this.particles){const t=i.size*(1+.2*Math.sin(i.pulse));this.config.particleBlur>0&&(this.ctx.shadowColor=i.color,this.ctx.shadowBlur=4*this.config.particleBlur),this.ctx.beginPath(),this.ctx.arc(i.x,i.y,t,0,2*Math.PI),this.ctx.fillStyle=i.color,this.ctx.fill(),this.ctx.shadowBlur=0}}updateFPS(){this.frameCount++;const i=Date.now(),t=i-this.lastFpsUpdate;t>=1e3&&(this.fps=Math.round(1e3*this.frameCount/t),this.frameCount=0,this.lastFpsUpdate=i)}animate(){if(!this.isRunning)return;const i=performance.now(),t=i-this.lastFrameTime,s=Math.min(Math.max(t,1),100);this.updateParticles(s),this.drawParticles(),this.updateFPS(),this.lastFrameTime=i,this.animationId=requestAnimationFrame(()=>this.animate())}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.animate())}pause(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}reset(){const i=this.isRunning;i&&this.pause(),this.createParticles(),i?this.start():this.drawParticles()}resize(){if(this.config.isBackground){const i=this.canvas.width,t=this.canvas.height,s=window.innerWidth,e=window.innerHeight;if(this.canvas.width=s,this.canvas.height=e,this.particles.length>0){const a=s/i,n=e/t;for(const i of this.particles)if(i.x*=a,i.y*=n,i.x=Math.max(0,Math.min(s,i.x)),i.y=Math.max(0,Math.min(e,i.y)),(i.x<=0||i.x>=s)&&(i.vx*=-1),(i.y<=0||i.y>=e)&&(i.vy*=-1),this.config.showTrail)for(let t=0;t<i.trailPositions.length;t++){const r=i.trailPositions[t];r.x*=a,r.y*=n,r.x=Math.max(0,Math.min(s,r.x)),r.y=Math.max(0,Math.min(e,r.y))}this.drawParticles()}else this.createParticles(),this.drawParticles()}}destroy(){this.pause(),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}bindEvents(){window.addEventListener("resize",()=>{this.config.isBackground&&(this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resize()},150))}),document.addEventListener("visibilitychange",()=>{document.hidden?(this.wasRunningBeforeHide=this.isRunning,this.isRunning&&this.pause()):(this.wasRunningBeforeHide&&this.start(),this.wasRunningBeforeHide=!1)})}}const t=i;exports.ParticleCanvas=i,exports.default=t;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});class i{constructor(i={}){this.MAX_PARTICLE_NUMBER=800,this.MAX_PARTICLE_SPEED=3,this.MAX_PARTICLE_SIZE=10,this.MAX_LINK_DISTANCE=300,this.MAX_LINE_WIDTH=5,this.MAX_LINE_OPACITY=1,this.MAX_TRAIL_VALUE=1,this.MAX_PARTICLE_BLUR=5,this.MAX_TRAIL_INTENSITY=5;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgb(10, 10, 25)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",particleBlur:void 0!==t.particleBlur?t.particleBlur:2,lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLine:void 0===t.showLine||t.showLine,canvasSize:t.canvasSize||[800,600],showTrail:void 0===t.showTrail||t.showTrail,trailIntensity:t.trailIntensity||2},this.particles=[],this.animationId=null,this.isRunning=!1,this.lastTime=0,this.fps=60,this.fpsInterval=1e3/60,this.then=Date.now(),this.frameCount=0,this.lastFpsUpdate=Date.now(),this.resizeTimer=null,this.wasRunningBeforeHide=!1,this.lastFrameTime=performance.now(),this.init()}validateAndLimitOptions(i){const t=Object.assign({},i);return void 0!==i.particleNumber&&(i.particleNumber>this.MAX_PARTICLE_NUMBER?(console.warn(`Warning: particleNumber (${i.particleNumber}) exceeds maximum allowed value (${this.MAX_PARTICLE_NUMBER}). Using maximum value instead.`),t.particleNumber=this.MAX_PARTICLE_NUMBER):i.particleNumber<1&&(console.warn(`Warning: particleNumber (${i.particleNumber}) is below minimum value (1). Using default value instead.`),t.particleNumber=150)),void 0!==i.particleSpeed&&(i.particleSpeed>this.MAX_PARTICLE_SPEED?(console.warn(`Warning: particleSpeed (${i.particleSpeed}) exceeds maximum allowed value (${this.MAX_PARTICLE_SPEED}). Using maximum value instead.`),t.particleSpeed=this.MAX_PARTICLE_SPEED):i.particleSpeed<0&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0). Using default value instead.`),t.particleSpeed=1)),void 0!==i.particleSize&&(i.particleSize>this.MAX_PARTICLE_SIZE?(console.warn(`Warning: particleSize (${i.particleSize}) exceeds maximum allowed value (${this.MAX_PARTICLE_SIZE}). Using maximum value instead.`),t.particleSize=this.MAX_PARTICLE_SIZE):i.particleSize<1&&(console.warn(`Warning: particleSize (${i.particleSize}) is below minimum value (1). Using default value instead.`),t.particleSize=3)),void 0!==i.particleBlur&&(i.particleBlur>this.MAX_PARTICLE_BLUR?(console.warn(`Warning: particleBlur (${i.particleBlur}) exceeds maximum allowed value (${this.MAX_PARTICLE_BLUR}). Using maximum value instead.`),t.particleBlur=this.MAX_PARTICLE_BLUR):i.particleBlur<0&&(console.warn(`Warning: particleBlur (${i.particleBlur}) is below minimum value (0). Using default value instead.`),t.particleBlur=2)),void 0!==i.linkDistance&&(i.linkDistance>this.MAX_LINK_DISTANCE?(console.warn(`Warning: linkDistance (${i.linkDistance}) exceeds maximum allowed value (${this.MAX_LINK_DISTANCE}). Using maximum value instead.`),t.linkDistance=this.MAX_LINK_DISTANCE):i.linkDistance<10&&(console.warn(`Warning: linkDistance (${i.linkDistance}) is below minimum value (10). Using default value instead.`),t.linkDistance=120)),void 0!==i.lineWidth&&(i.lineWidth>this.MAX_LINE_WIDTH?(console.warn(`Warning: lineWidth (${i.lineWidth}) exceeds maximum allowed value (${this.MAX_LINE_WIDTH}). Using maximum value instead.`),t.lineWidth=this.MAX_LINE_WIDTH):i.lineWidth<0&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0). Using default value instead.`),t.lineWidth=1)),void 0!==i.lineOpacity&&(i.lineOpacity>this.MAX_LINE_OPACITY?(console.warn(`Warning: lineOpacity (${i.lineOpacity}) exceeds maximum allowed value (${this.MAX_LINE_OPACITY}). Using maximum value instead.`),t.lineOpacity=this.MAX_LINE_OPACITY):i.lineOpacity<0&&(console.warn(`Warning: lineOpacity (${i.lineOpacity}) is below minimum value (0). Using default value instead.`),t.lineOpacity=.3)),void 0!==i.trailIntensity&&(i.trailIntensity>this.MAX_TRAIL_INTENSITY?(console.warn(`Warning: trailIntensity (${i.trailIntensity}) exceeds maximum allowed value (${this.MAX_TRAIL_INTENSITY}). Using maximum value instead.`),t.trailIntensity=this.MAX_TRAIL_INTENSITY):i.trailIntensity<1&&(console.warn(`Warning: trailIntensity (${i.trailIntensity}) is below minimum value (1). Using default value instead.`),t.trailIntensity=2)),t}init(){this.canvas=document.createElement("canvas");const i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");if(this.ctx=i,"string"==typeof this.config.canvasContainer){const i=document.querySelector(this.config.canvasContainer);if(!i)throw new Error(`Canvas container not found: ${this.config.canvasContainer}`);this.container=i}else this.container=this.config.canvasContainer;this.container?(this.container.appendChild(this.canvas),this.setupCanvas(),this.createParticles(),this.bindEvents()):console.error("Canvas container not found")}setupCanvas(){if(this.config.isBackground)this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.zIndex="-1",this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;else{this.canvas.style.display="block";const[i,t]=this.config.canvasSize;this.canvas.width=i,this.canvas.height=t,this.canvas.style.width=i+"px",this.canvas.style.height=t+"px"}this.canvas.style.pointerEvents="none"}createParticles(){this.particles=[];const i=Array.isArray(this.config.particleColor);for(let t=0;t<this.config.particleNumber;t++){let t;if(i){const i=this.config.particleColor;t=i[Math.floor(Math.random()*i.length)]}else t=this.config.particleColor;this.particles.push({x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:2*(Math.random()-.5)*this.config.particleSpeed,vy:2*(Math.random()-.5)*this.config.particleSpeed,size:this.config.particleSize,color:t,originalColor:t,pulse:0,pulseSpeed:.05*Math.random()+.02,trailPositions:[]})}}updateParticles(i){const t=i/16.67;for(const i of this.particles)i.pulse+=i.pulseSpeed*t,i.pulse>2*Math.PI&&(i.pulse=0),this.config.showTrail&&(i.trailPositions.unshift({x:i.x,y:i.y}),i.trailPositions.length>10*this.config.trailIntensity&&(i.trailPositions.length=10*this.config.trailIntensity)),i.x+=i.vx*t,i.y+=i.vy*t,(i.x<0||i.x>this.canvas.width)&&(i.vx*=-1),(i.y<0||i.y>this.canvas.height)&&(i.vy*=-1),i.x=Math.max(0,Math.min(this.canvas.width,i.x)),i.y=Math.max(0,Math.min(this.canvas.height,i.y))}drawTrailEffect(){if(this.config.showTrail){this.ctx.save();for(const i of this.particles){if(i.trailPositions.length<2)continue;this.ctx.beginPath(),this.ctx.moveTo(i.trailPositions[0].x,i.trailPositions[0].y);for(let t=1;t<i.trailPositions.length;t++)this.ctx.lineTo(i.trailPositions[t].x,i.trailPositions[t].y);const t=1.2*i.size;this.ctx.lineWidth=t,this.ctx.lineCap="round",this.ctx.lineJoin="round";const s=i.trailPositions[0],e=i.trailPositions[i.trailPositions.length-1],a=this.ctx.createLinearGradient(s.x,s.y,e.x,e.y),n=this.parseColor(i.color),r=.35;a.addColorStop(0,`rgba(${n.r}, ${n.g}, ${n.b}, ${r})`),a.addColorStop(.3,`rgba(${n.r}, ${n.g}, ${n.b}, ${.6*r})`),a.addColorStop(.7,`rgba(${n.r}, ${n.g}, ${n.b}, ${.2*r})`),a.addColorStop(1,`rgba(${n.r}, ${n.g}, ${n.b}, 0)`),this.ctx.strokeStyle=a,this.ctx.stroke()}this.ctx.restore()}}parseColor(i){if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3]),a:parseFloat(t[4])}}else if(i.startsWith("rgb")){const t=i.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3])}}else if(i.startsWith("#")){let t,s,e,a=i.replace("#","");if(3===a.length)t=parseInt(a[0]+a[0],16),s=parseInt(a[1]+a[1],16),e=parseInt(a[2]+a[2],16);else{if(6!==a.length)return{r:255,g:255,b:255};t=parseInt(a.substring(0,2),16),s=parseInt(a.substring(2,4),16),e=parseInt(a.substring(4,6),16)}return{r:t,g:s,b:e}}return{r:255,g:255,b:255}}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);let i=this.config.canvasBackgroundColor;if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t){const s=t[1],e=t[2],a=t[3];parseFloat(t[4])<1&&(i=`rgb(${s}, ${e}, ${a})`)}}if(this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.drawTrailEffect(),this.config.showLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const s=this.particles[i].x-this.particles[t].x,e=this.particles[i].y-this.particles[t].y,a=Math.sqrt(s*s+e*e);if(a<this.config.linkDistance){const s=this.config.lineOpacity*(1-a/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=s,this.ctx.lineWidth=this.config.lineWidth,this.ctx.beginPath(),this.ctx.moveTo(this.particles[i].x,this.particles[i].y),this.ctx.lineTo(this.particles[t].x,this.particles[t].y),this.ctx.stroke()}}this.ctx.globalAlpha=1;for(const i of this.particles){const t=i.size*(1+.2*Math.sin(i.pulse));this.config.particleBlur>0&&(this.ctx.shadowColor=i.color,this.ctx.shadowBlur=4*this.config.particleBlur),this.ctx.beginPath(),this.ctx.arc(i.x,i.y,t,0,2*Math.PI),this.ctx.fillStyle=i.color,this.ctx.fill(),this.ctx.shadowBlur=0}}updateFPS(){this.frameCount++;const i=Date.now(),t=i-this.lastFpsUpdate;t>=1e3&&(this.fps=Math.round(1e3*this.frameCount/t),this.frameCount=0,this.lastFpsUpdate=i)}animate(){if(!this.isRunning)return;const i=performance.now(),t=i-this.lastFrameTime,s=Math.min(Math.max(t,1),100);this.updateParticles(s),this.drawParticles(),this.updateFPS(),this.lastFrameTime=i,this.animationId=requestAnimationFrame(()=>this.animate())}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.animate())}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}reset(){const i=this.isRunning;i&&this.stop(),this.createParticles(),i?this.start():this.drawParticles()}resize(){if(this.config.isBackground){const i=this.canvas.width,t=this.canvas.height,s=window.innerWidth,e=window.innerHeight;if(this.canvas.width=s,this.canvas.height=e,this.particles.length>0){const a=s/i,n=e/t;for(const i of this.particles)if(i.x*=a,i.y*=n,i.x=Math.max(0,Math.min(s,i.x)),i.y=Math.max(0,Math.min(e,i.y)),(i.x<=0||i.x>=s)&&(i.vx*=-1),(i.y<=0||i.y>=e)&&(i.vy*=-1),this.config.showTrail)for(let t=0;t<i.trailPositions.length;t++){const r=i.trailPositions[t];r.x*=a,r.y*=n,r.x=Math.max(0,Math.min(s,r.x)),r.y=Math.max(0,Math.min(e,r.y))}this.drawParticles()}else this.createParticles(),this.drawParticles()}}destroy(){this.stop(),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}bindEvents(){window.addEventListener("resize",()=>{this.config.isBackground&&(this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resize()},150))}),document.addEventListener("visibilitychange",()=>{document.hidden?(this.wasRunningBeforeHide=this.isRunning,this.isRunning&&this.stop()):(this.wasRunningBeforeHide&&this.start(),this.wasRunningBeforeHide=!1)})}}const t=i;exports.ParticleCanvas=i,exports.default=t;
@@ -1 +1 @@
1
- class i{constructor(i={}){this.MAX_PARTICLE_NUMBER=800,this.MAX_PARTICLE_SPEED=3,this.MAX_PARTICLE_SIZE=10,this.MAX_LINK_DISTANCE=300,this.MAX_LINE_WIDTH=5,this.MAX_LINE_OPACITY=1,this.MAX_TRAIL_VALUE=1,this.MAX_PARTICLE_BLUR=5,this.MAX_TRAIL_INTENSITY=5;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgb(10, 10, 25)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",particleBlur:void 0!==t.particleBlur?t.particleBlur:2,lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLine:void 0===t.showLine||t.showLine,canvasSize:t.canvasSize||[800,600],showTrail:void 0===t.showTrail||t.showTrail,trailIntensity:t.trailIntensity||2},this.particles=[],this.animationId=null,this.isRunning=!1,this.lastTime=0,this.fps=60,this.fpsInterval=1e3/60,this.then=Date.now(),this.frameCount=0,this.lastFpsUpdate=Date.now(),this.resizeTimer=null,this.wasRunningBeforeHide=!1,this.lastFrameTime=performance.now(),this.init()}validateAndLimitOptions(i){const t=Object.assign({},i);return void 0!==i.particleNumber&&(i.particleNumber>this.MAX_PARTICLE_NUMBER?(console.warn(`Warning: particleNumber (${i.particleNumber}) exceeds maximum allowed value (${this.MAX_PARTICLE_NUMBER}). Using maximum value instead.`),t.particleNumber=this.MAX_PARTICLE_NUMBER):i.particleNumber<1&&(console.warn(`Warning: particleNumber (${i.particleNumber}) is below minimum value (1). Using default value instead.`),t.particleNumber=150)),void 0!==i.particleSpeed&&(i.particleSpeed>this.MAX_PARTICLE_SPEED?(console.warn(`Warning: particleSpeed (${i.particleSpeed}) exceeds maximum allowed value (${this.MAX_PARTICLE_SPEED}). Using maximum value instead.`),t.particleSpeed=this.MAX_PARTICLE_SPEED):i.particleSpeed<0&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0). Using default value instead.`),t.particleSpeed=1)),void 0!==i.particleSize&&(i.particleSize>this.MAX_PARTICLE_SIZE?(console.warn(`Warning: particleSize (${i.particleSize}) exceeds maximum allowed value (${this.MAX_PARTICLE_SIZE}). Using maximum value instead.`),t.particleSize=this.MAX_PARTICLE_SIZE):i.particleSize<1&&(console.warn(`Warning: particleSize (${i.particleSize}) is below minimum value (1). Using default value instead.`),t.particleSize=3)),void 0!==i.particleBlur&&(i.particleBlur>this.MAX_PARTICLE_BLUR?(console.warn(`Warning: particleBlur (${i.particleBlur}) exceeds maximum allowed value (${this.MAX_PARTICLE_BLUR}). Using maximum value instead.`),t.particleBlur=this.MAX_PARTICLE_BLUR):i.particleBlur<0&&(console.warn(`Warning: particleBlur (${i.particleBlur}) is below minimum value (0). Using default value instead.`),t.particleBlur=2)),void 0!==i.linkDistance&&(i.linkDistance>this.MAX_LINK_DISTANCE?(console.warn(`Warning: linkDistance (${i.linkDistance}) exceeds maximum allowed value (${this.MAX_LINK_DISTANCE}). Using maximum value instead.`),t.linkDistance=this.MAX_LINK_DISTANCE):i.linkDistance<10&&(console.warn(`Warning: linkDistance (${i.linkDistance}) is below minimum value (10). Using default value instead.`),t.linkDistance=120)),void 0!==i.lineWidth&&(i.lineWidth>this.MAX_LINE_WIDTH?(console.warn(`Warning: lineWidth (${i.lineWidth}) exceeds maximum allowed value (${this.MAX_LINE_WIDTH}). Using maximum value instead.`),t.lineWidth=this.MAX_LINE_WIDTH):i.lineWidth<0&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0). Using default value instead.`),t.lineWidth=1)),void 0!==i.lineOpacity&&(i.lineOpacity>this.MAX_LINE_OPACITY?(console.warn(`Warning: lineOpacity (${i.lineOpacity}) exceeds maximum allowed value (${this.MAX_LINE_OPACITY}). Using maximum value instead.`),t.lineOpacity=this.MAX_LINE_OPACITY):i.lineOpacity<0&&(console.warn(`Warning: lineOpacity (${i.lineOpacity}) is below minimum value (0). Using default value instead.`),t.lineOpacity=.3)),void 0!==i.trailIntensity&&(i.trailIntensity>this.MAX_TRAIL_INTENSITY?(console.warn(`Warning: trailIntensity (${i.trailIntensity}) exceeds maximum allowed value (${this.MAX_TRAIL_INTENSITY}). Using maximum value instead.`),t.trailIntensity=this.MAX_TRAIL_INTENSITY):i.trailIntensity<1&&(console.warn(`Warning: trailIntensity (${i.trailIntensity}) is below minimum value (1). Using default value instead.`),t.trailIntensity=2)),t}init(){this.canvas=document.createElement("canvas");const i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");if(this.ctx=i,"string"==typeof this.config.canvasContainer){const i=document.querySelector(this.config.canvasContainer);if(!i)throw new Error(`Canvas container not found: ${this.config.canvasContainer}`);this.container=i}else this.container=this.config.canvasContainer;this.container?(this.container.appendChild(this.canvas),this.setupCanvas(),this.createParticles(),this.bindEvents()):console.error("Canvas container not found")}setupCanvas(){if(this.config.isBackground)this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.zIndex="-1",this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;else{this.canvas.style.display="block";const[i,t]=this.config.canvasSize;this.canvas.width=i,this.canvas.height=t,this.canvas.style.width=i+"px",this.canvas.style.height=t+"px"}this.canvas.style.pointerEvents="none"}createParticles(){this.particles=[];const i=Array.isArray(this.config.particleColor);for(let t=0;t<this.config.particleNumber;t++){let t;if(i){const i=this.config.particleColor;t=i[Math.floor(Math.random()*i.length)]}else t=this.config.particleColor;this.particles.push({x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:2*(Math.random()-.5)*this.config.particleSpeed,vy:2*(Math.random()-.5)*this.config.particleSpeed,size:this.config.particleSize,color:t,originalColor:t,pulse:0,pulseSpeed:.05*Math.random()+.02,trailPositions:[]})}}updateParticles(i){const t=i/16.67;for(const i of this.particles)i.pulse+=i.pulseSpeed*t,i.pulse>2*Math.PI&&(i.pulse=0),this.config.showTrail&&(i.trailPositions.unshift({x:i.x,y:i.y}),i.trailPositions.length>10*this.config.trailIntensity&&(i.trailPositions.length=10*this.config.trailIntensity)),i.x+=i.vx*t,i.y+=i.vy*t,(i.x<0||i.x>this.canvas.width)&&(i.vx*=-1),(i.y<0||i.y>this.canvas.height)&&(i.vy*=-1),i.x=Math.max(0,Math.min(this.canvas.width,i.x)),i.y=Math.max(0,Math.min(this.canvas.height,i.y))}drawTrailEffect(){if(this.config.showTrail){this.ctx.save();for(const i of this.particles){if(i.trailPositions.length<2)continue;this.ctx.beginPath(),this.ctx.moveTo(i.trailPositions[0].x,i.trailPositions[0].y);for(let t=1;t<i.trailPositions.length;t++)this.ctx.lineTo(i.trailPositions[t].x,i.trailPositions[t].y);const t=1.2*i.size;this.ctx.lineWidth=t,this.ctx.lineCap="round",this.ctx.lineJoin="round";const s=i.trailPositions[0],e=i.trailPositions[i.trailPositions.length-1],a=this.ctx.createLinearGradient(s.x,s.y,e.x,e.y),n=this.parseColor(i.color),r=.35;a.addColorStop(0,`rgba(${n.r}, ${n.g}, ${n.b}, ${r})`),a.addColorStop(.3,`rgba(${n.r}, ${n.g}, ${n.b}, ${.6*r})`),a.addColorStop(.7,`rgba(${n.r}, ${n.g}, ${n.b}, ${.2*r})`),a.addColorStop(1,`rgba(${n.r}, ${n.g}, ${n.b}, 0)`),this.ctx.strokeStyle=a,this.ctx.stroke()}this.ctx.restore()}}parseColor(i){if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3]),a:parseFloat(t[4])}}else if(i.startsWith("rgb")){const t=i.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3])}}else if(i.startsWith("#")){let t,s,e,a=i.replace("#","");if(3===a.length)t=parseInt(a[0]+a[0],16),s=parseInt(a[1]+a[1],16),e=parseInt(a[2]+a[2],16);else{if(6!==a.length)return{r:255,g:255,b:255};t=parseInt(a.substring(0,2),16),s=parseInt(a.substring(2,4),16),e=parseInt(a.substring(4,6),16)}return{r:t,g:s,b:e}}return{r:255,g:255,b:255}}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);let i=this.config.canvasBackgroundColor;if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t){const s=t[1],e=t[2],a=t[3];parseFloat(t[4])<1&&(i=`rgb(${s}, ${e}, ${a})`)}}if(this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.drawTrailEffect(),this.config.showLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const s=this.particles[i].x-this.particles[t].x,e=this.particles[i].y-this.particles[t].y,a=Math.sqrt(s*s+e*e);if(a<this.config.linkDistance){const s=this.config.lineOpacity*(1-a/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=s,this.ctx.lineWidth=this.config.lineWidth,this.ctx.beginPath(),this.ctx.moveTo(this.particles[i].x,this.particles[i].y),this.ctx.lineTo(this.particles[t].x,this.particles[t].y),this.ctx.stroke()}}this.ctx.globalAlpha=1;for(const i of this.particles){const t=i.size*(1+.2*Math.sin(i.pulse));this.config.particleBlur>0&&(this.ctx.shadowColor=i.color,this.ctx.shadowBlur=4*this.config.particleBlur),this.ctx.beginPath(),this.ctx.arc(i.x,i.y,t,0,2*Math.PI),this.ctx.fillStyle=i.color,this.ctx.fill(),this.ctx.shadowBlur=0}}updateFPS(){this.frameCount++;const i=Date.now(),t=i-this.lastFpsUpdate;t>=1e3&&(this.fps=Math.round(1e3*this.frameCount/t),this.frameCount=0,this.lastFpsUpdate=i)}animate(){if(!this.isRunning)return;const i=performance.now(),t=i-this.lastFrameTime,s=Math.min(Math.max(t,1),100);this.updateParticles(s),this.drawParticles(),this.updateFPS(),this.lastFrameTime=i,this.animationId=requestAnimationFrame(()=>this.animate())}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.animate())}pause(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}reset(){const i=this.isRunning;i&&this.pause(),this.createParticles(),i?this.start():this.drawParticles()}resize(){if(this.config.isBackground){const i=this.canvas.width,t=this.canvas.height,s=window.innerWidth,e=window.innerHeight;if(this.canvas.width=s,this.canvas.height=e,this.particles.length>0){const a=s/i,n=e/t;for(const i of this.particles)if(i.x*=a,i.y*=n,i.x=Math.max(0,Math.min(s,i.x)),i.y=Math.max(0,Math.min(e,i.y)),(i.x<=0||i.x>=s)&&(i.vx*=-1),(i.y<=0||i.y>=e)&&(i.vy*=-1),this.config.showTrail)for(let t=0;t<i.trailPositions.length;t++){const r=i.trailPositions[t];r.x*=a,r.y*=n,r.x=Math.max(0,Math.min(s,r.x)),r.y=Math.max(0,Math.min(e,r.y))}this.drawParticles()}else this.createParticles(),this.drawParticles()}}destroy(){this.pause(),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}bindEvents(){window.addEventListener("resize",()=>{this.config.isBackground&&(this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resize()},150))}),document.addEventListener("visibilitychange",()=>{document.hidden?(this.wasRunningBeforeHide=this.isRunning,this.isRunning&&this.pause()):(this.wasRunningBeforeHide&&this.start(),this.wasRunningBeforeHide=!1)})}}const t=i;export{i as ParticleCanvas,t as default};
1
+ class i{constructor(i={}){this.MAX_PARTICLE_NUMBER=800,this.MAX_PARTICLE_SPEED=3,this.MAX_PARTICLE_SIZE=10,this.MAX_LINK_DISTANCE=300,this.MAX_LINE_WIDTH=5,this.MAX_LINE_OPACITY=1,this.MAX_TRAIL_VALUE=1,this.MAX_PARTICLE_BLUR=5,this.MAX_TRAIL_INTENSITY=5;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgb(10, 10, 25)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",particleBlur:void 0!==t.particleBlur?t.particleBlur:2,lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLine:void 0===t.showLine||t.showLine,canvasSize:t.canvasSize||[800,600],showTrail:void 0===t.showTrail||t.showTrail,trailIntensity:t.trailIntensity||2},this.particles=[],this.animationId=null,this.isRunning=!1,this.lastTime=0,this.fps=60,this.fpsInterval=1e3/60,this.then=Date.now(),this.frameCount=0,this.lastFpsUpdate=Date.now(),this.resizeTimer=null,this.wasRunningBeforeHide=!1,this.lastFrameTime=performance.now(),this.init()}validateAndLimitOptions(i){const t=Object.assign({},i);return void 0!==i.particleNumber&&(i.particleNumber>this.MAX_PARTICLE_NUMBER?(console.warn(`Warning: particleNumber (${i.particleNumber}) exceeds maximum allowed value (${this.MAX_PARTICLE_NUMBER}). Using maximum value instead.`),t.particleNumber=this.MAX_PARTICLE_NUMBER):i.particleNumber<1&&(console.warn(`Warning: particleNumber (${i.particleNumber}) is below minimum value (1). Using default value instead.`),t.particleNumber=150)),void 0!==i.particleSpeed&&(i.particleSpeed>this.MAX_PARTICLE_SPEED?(console.warn(`Warning: particleSpeed (${i.particleSpeed}) exceeds maximum allowed value (${this.MAX_PARTICLE_SPEED}). Using maximum value instead.`),t.particleSpeed=this.MAX_PARTICLE_SPEED):i.particleSpeed<0&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0). Using default value instead.`),t.particleSpeed=1)),void 0!==i.particleSize&&(i.particleSize>this.MAX_PARTICLE_SIZE?(console.warn(`Warning: particleSize (${i.particleSize}) exceeds maximum allowed value (${this.MAX_PARTICLE_SIZE}). Using maximum value instead.`),t.particleSize=this.MAX_PARTICLE_SIZE):i.particleSize<1&&(console.warn(`Warning: particleSize (${i.particleSize}) is below minimum value (1). Using default value instead.`),t.particleSize=3)),void 0!==i.particleBlur&&(i.particleBlur>this.MAX_PARTICLE_BLUR?(console.warn(`Warning: particleBlur (${i.particleBlur}) exceeds maximum allowed value (${this.MAX_PARTICLE_BLUR}). Using maximum value instead.`),t.particleBlur=this.MAX_PARTICLE_BLUR):i.particleBlur<0&&(console.warn(`Warning: particleBlur (${i.particleBlur}) is below minimum value (0). Using default value instead.`),t.particleBlur=2)),void 0!==i.linkDistance&&(i.linkDistance>this.MAX_LINK_DISTANCE?(console.warn(`Warning: linkDistance (${i.linkDistance}) exceeds maximum allowed value (${this.MAX_LINK_DISTANCE}). Using maximum value instead.`),t.linkDistance=this.MAX_LINK_DISTANCE):i.linkDistance<10&&(console.warn(`Warning: linkDistance (${i.linkDistance}) is below minimum value (10). Using default value instead.`),t.linkDistance=120)),void 0!==i.lineWidth&&(i.lineWidth>this.MAX_LINE_WIDTH?(console.warn(`Warning: lineWidth (${i.lineWidth}) exceeds maximum allowed value (${this.MAX_LINE_WIDTH}). Using maximum value instead.`),t.lineWidth=this.MAX_LINE_WIDTH):i.lineWidth<0&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0). Using default value instead.`),t.lineWidth=1)),void 0!==i.lineOpacity&&(i.lineOpacity>this.MAX_LINE_OPACITY?(console.warn(`Warning: lineOpacity (${i.lineOpacity}) exceeds maximum allowed value (${this.MAX_LINE_OPACITY}). Using maximum value instead.`),t.lineOpacity=this.MAX_LINE_OPACITY):i.lineOpacity<0&&(console.warn(`Warning: lineOpacity (${i.lineOpacity}) is below minimum value (0). Using default value instead.`),t.lineOpacity=.3)),void 0!==i.trailIntensity&&(i.trailIntensity>this.MAX_TRAIL_INTENSITY?(console.warn(`Warning: trailIntensity (${i.trailIntensity}) exceeds maximum allowed value (${this.MAX_TRAIL_INTENSITY}). Using maximum value instead.`),t.trailIntensity=this.MAX_TRAIL_INTENSITY):i.trailIntensity<1&&(console.warn(`Warning: trailIntensity (${i.trailIntensity}) is below minimum value (1). Using default value instead.`),t.trailIntensity=2)),t}init(){this.canvas=document.createElement("canvas");const i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");if(this.ctx=i,"string"==typeof this.config.canvasContainer){const i=document.querySelector(this.config.canvasContainer);if(!i)throw new Error(`Canvas container not found: ${this.config.canvasContainer}`);this.container=i}else this.container=this.config.canvasContainer;this.container?(this.container.appendChild(this.canvas),this.setupCanvas(),this.createParticles(),this.bindEvents()):console.error("Canvas container not found")}setupCanvas(){if(this.config.isBackground)this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.zIndex="-1",this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;else{this.canvas.style.display="block";const[i,t]=this.config.canvasSize;this.canvas.width=i,this.canvas.height=t,this.canvas.style.width=i+"px",this.canvas.style.height=t+"px"}this.canvas.style.pointerEvents="none"}createParticles(){this.particles=[];const i=Array.isArray(this.config.particleColor);for(let t=0;t<this.config.particleNumber;t++){let t;if(i){const i=this.config.particleColor;t=i[Math.floor(Math.random()*i.length)]}else t=this.config.particleColor;this.particles.push({x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:2*(Math.random()-.5)*this.config.particleSpeed,vy:2*(Math.random()-.5)*this.config.particleSpeed,size:this.config.particleSize,color:t,originalColor:t,pulse:0,pulseSpeed:.05*Math.random()+.02,trailPositions:[]})}}updateParticles(i){const t=i/16.67;for(const i of this.particles)i.pulse+=i.pulseSpeed*t,i.pulse>2*Math.PI&&(i.pulse=0),this.config.showTrail&&(i.trailPositions.unshift({x:i.x,y:i.y}),i.trailPositions.length>10*this.config.trailIntensity&&(i.trailPositions.length=10*this.config.trailIntensity)),i.x+=i.vx*t,i.y+=i.vy*t,(i.x<0||i.x>this.canvas.width)&&(i.vx*=-1),(i.y<0||i.y>this.canvas.height)&&(i.vy*=-1),i.x=Math.max(0,Math.min(this.canvas.width,i.x)),i.y=Math.max(0,Math.min(this.canvas.height,i.y))}drawTrailEffect(){if(this.config.showTrail){this.ctx.save();for(const i of this.particles){if(i.trailPositions.length<2)continue;this.ctx.beginPath(),this.ctx.moveTo(i.trailPositions[0].x,i.trailPositions[0].y);for(let t=1;t<i.trailPositions.length;t++)this.ctx.lineTo(i.trailPositions[t].x,i.trailPositions[t].y);const t=1.2*i.size;this.ctx.lineWidth=t,this.ctx.lineCap="round",this.ctx.lineJoin="round";const s=i.trailPositions[0],e=i.trailPositions[i.trailPositions.length-1],a=this.ctx.createLinearGradient(s.x,s.y,e.x,e.y),n=this.parseColor(i.color),r=.35;a.addColorStop(0,`rgba(${n.r}, ${n.g}, ${n.b}, ${r})`),a.addColorStop(.3,`rgba(${n.r}, ${n.g}, ${n.b}, ${.6*r})`),a.addColorStop(.7,`rgba(${n.r}, ${n.g}, ${n.b}, ${.2*r})`),a.addColorStop(1,`rgba(${n.r}, ${n.g}, ${n.b}, 0)`),this.ctx.strokeStyle=a,this.ctx.stroke()}this.ctx.restore()}}parseColor(i){if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3]),a:parseFloat(t[4])}}else if(i.startsWith("rgb")){const t=i.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3])}}else if(i.startsWith("#")){let t,s,e,a=i.replace("#","");if(3===a.length)t=parseInt(a[0]+a[0],16),s=parseInt(a[1]+a[1],16),e=parseInt(a[2]+a[2],16);else{if(6!==a.length)return{r:255,g:255,b:255};t=parseInt(a.substring(0,2),16),s=parseInt(a.substring(2,4),16),e=parseInt(a.substring(4,6),16)}return{r:t,g:s,b:e}}return{r:255,g:255,b:255}}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);let i=this.config.canvasBackgroundColor;if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t){const s=t[1],e=t[2],a=t[3];parseFloat(t[4])<1&&(i=`rgb(${s}, ${e}, ${a})`)}}if(this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.drawTrailEffect(),this.config.showLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const s=this.particles[i].x-this.particles[t].x,e=this.particles[i].y-this.particles[t].y,a=Math.sqrt(s*s+e*e);if(a<this.config.linkDistance){const s=this.config.lineOpacity*(1-a/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=s,this.ctx.lineWidth=this.config.lineWidth,this.ctx.beginPath(),this.ctx.moveTo(this.particles[i].x,this.particles[i].y),this.ctx.lineTo(this.particles[t].x,this.particles[t].y),this.ctx.stroke()}}this.ctx.globalAlpha=1;for(const i of this.particles){const t=i.size*(1+.2*Math.sin(i.pulse));this.config.particleBlur>0&&(this.ctx.shadowColor=i.color,this.ctx.shadowBlur=4*this.config.particleBlur),this.ctx.beginPath(),this.ctx.arc(i.x,i.y,t,0,2*Math.PI),this.ctx.fillStyle=i.color,this.ctx.fill(),this.ctx.shadowBlur=0}}updateFPS(){this.frameCount++;const i=Date.now(),t=i-this.lastFpsUpdate;t>=1e3&&(this.fps=Math.round(1e3*this.frameCount/t),this.frameCount=0,this.lastFpsUpdate=i)}animate(){if(!this.isRunning)return;const i=performance.now(),t=i-this.lastFrameTime,s=Math.min(Math.max(t,1),100);this.updateParticles(s),this.drawParticles(),this.updateFPS(),this.lastFrameTime=i,this.animationId=requestAnimationFrame(()=>this.animate())}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.animate())}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}reset(){const i=this.isRunning;i&&this.stop(),this.createParticles(),i?this.start():this.drawParticles()}resize(){if(this.config.isBackground){const i=this.canvas.width,t=this.canvas.height,s=window.innerWidth,e=window.innerHeight;if(this.canvas.width=s,this.canvas.height=e,this.particles.length>0){const a=s/i,n=e/t;for(const i of this.particles)if(i.x*=a,i.y*=n,i.x=Math.max(0,Math.min(s,i.x)),i.y=Math.max(0,Math.min(e,i.y)),(i.x<=0||i.x>=s)&&(i.vx*=-1),(i.y<=0||i.y>=e)&&(i.vy*=-1),this.config.showTrail)for(let t=0;t<i.trailPositions.length;t++){const r=i.trailPositions[t];r.x*=a,r.y*=n,r.x=Math.max(0,Math.min(s,r.x)),r.y=Math.max(0,Math.min(e,r.y))}this.drawParticles()}else this.createParticles(),this.drawParticles()}}destroy(){this.stop(),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}bindEvents(){window.addEventListener("resize",()=>{this.config.isBackground&&(this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resize()},150))}),document.addEventListener("visibilitychange",()=>{document.hidden?(this.wasRunningBeforeHide=this.isRunning,this.isRunning&&this.stop()):(this.wasRunningBeforeHide&&this.start(),this.wasRunningBeforeHide=!1)})}}const t=i;export{i as ParticleCanvas,t as default};
package/dist/bundle.js CHANGED
@@ -1 +1 @@
1
- var ParticleCanvasPro=function(i){"use strict";class t{constructor(i={}){this.MAX_PARTICLE_NUMBER=800,this.MAX_PARTICLE_SPEED=3,this.MAX_PARTICLE_SIZE=10,this.MAX_LINK_DISTANCE=300,this.MAX_LINE_WIDTH=5,this.MAX_LINE_OPACITY=1,this.MAX_TRAIL_VALUE=1,this.MAX_PARTICLE_BLUR=5,this.MAX_TRAIL_INTENSITY=5;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgb(10, 10, 25)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",particleBlur:void 0!==t.particleBlur?t.particleBlur:2,lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLine:void 0===t.showLine||t.showLine,canvasSize:t.canvasSize||[800,600],showTrail:void 0===t.showTrail||t.showTrail,trailIntensity:t.trailIntensity||2},this.particles=[],this.animationId=null,this.isRunning=!1,this.lastTime=0,this.fps=60,this.fpsInterval=1e3/60,this.then=Date.now(),this.frameCount=0,this.lastFpsUpdate=Date.now(),this.resizeTimer=null,this.wasRunningBeforeHide=!1,this.lastFrameTime=performance.now(),this.init()}validateAndLimitOptions(i){const t=Object.assign({},i);return void 0!==i.particleNumber&&(i.particleNumber>this.MAX_PARTICLE_NUMBER?(console.warn(`Warning: particleNumber (${i.particleNumber}) exceeds maximum allowed value (${this.MAX_PARTICLE_NUMBER}). Using maximum value instead.`),t.particleNumber=this.MAX_PARTICLE_NUMBER):i.particleNumber<1&&(console.warn(`Warning: particleNumber (${i.particleNumber}) is below minimum value (1). Using default value instead.`),t.particleNumber=150)),void 0!==i.particleSpeed&&(i.particleSpeed>this.MAX_PARTICLE_SPEED?(console.warn(`Warning: particleSpeed (${i.particleSpeed}) exceeds maximum allowed value (${this.MAX_PARTICLE_SPEED}). Using maximum value instead.`),t.particleSpeed=this.MAX_PARTICLE_SPEED):i.particleSpeed<0&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0). Using default value instead.`),t.particleSpeed=1)),void 0!==i.particleSize&&(i.particleSize>this.MAX_PARTICLE_SIZE?(console.warn(`Warning: particleSize (${i.particleSize}) exceeds maximum allowed value (${this.MAX_PARTICLE_SIZE}). Using maximum value instead.`),t.particleSize=this.MAX_PARTICLE_SIZE):i.particleSize<1&&(console.warn(`Warning: particleSize (${i.particleSize}) is below minimum value (1). Using default value instead.`),t.particleSize=3)),void 0!==i.particleBlur&&(i.particleBlur>this.MAX_PARTICLE_BLUR?(console.warn(`Warning: particleBlur (${i.particleBlur}) exceeds maximum allowed value (${this.MAX_PARTICLE_BLUR}). Using maximum value instead.`),t.particleBlur=this.MAX_PARTICLE_BLUR):i.particleBlur<0&&(console.warn(`Warning: particleBlur (${i.particleBlur}) is below minimum value (0). Using default value instead.`),t.particleBlur=2)),void 0!==i.linkDistance&&(i.linkDistance>this.MAX_LINK_DISTANCE?(console.warn(`Warning: linkDistance (${i.linkDistance}) exceeds maximum allowed value (${this.MAX_LINK_DISTANCE}). Using maximum value instead.`),t.linkDistance=this.MAX_LINK_DISTANCE):i.linkDistance<10&&(console.warn(`Warning: linkDistance (${i.linkDistance}) is below minimum value (10). Using default value instead.`),t.linkDistance=120)),void 0!==i.lineWidth&&(i.lineWidth>this.MAX_LINE_WIDTH?(console.warn(`Warning: lineWidth (${i.lineWidth}) exceeds maximum allowed value (${this.MAX_LINE_WIDTH}). Using maximum value instead.`),t.lineWidth=this.MAX_LINE_WIDTH):i.lineWidth<0&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0). Using default value instead.`),t.lineWidth=1)),void 0!==i.lineOpacity&&(i.lineOpacity>this.MAX_LINE_OPACITY?(console.warn(`Warning: lineOpacity (${i.lineOpacity}) exceeds maximum allowed value (${this.MAX_LINE_OPACITY}). Using maximum value instead.`),t.lineOpacity=this.MAX_LINE_OPACITY):i.lineOpacity<0&&(console.warn(`Warning: lineOpacity (${i.lineOpacity}) is below minimum value (0). Using default value instead.`),t.lineOpacity=.3)),void 0!==i.trailIntensity&&(i.trailIntensity>this.MAX_TRAIL_INTENSITY?(console.warn(`Warning: trailIntensity (${i.trailIntensity}) exceeds maximum allowed value (${this.MAX_TRAIL_INTENSITY}). Using maximum value instead.`),t.trailIntensity=this.MAX_TRAIL_INTENSITY):i.trailIntensity<1&&(console.warn(`Warning: trailIntensity (${i.trailIntensity}) is below minimum value (1). Using default value instead.`),t.trailIntensity=2)),t}init(){this.canvas=document.createElement("canvas");const i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");if(this.ctx=i,"string"==typeof this.config.canvasContainer){const i=document.querySelector(this.config.canvasContainer);if(!i)throw new Error(`Canvas container not found: ${this.config.canvasContainer}`);this.container=i}else this.container=this.config.canvasContainer;this.container?(this.container.appendChild(this.canvas),this.setupCanvas(),this.createParticles(),this.bindEvents()):console.error("Canvas container not found")}setupCanvas(){if(this.config.isBackground)this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.zIndex="-1",this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;else{this.canvas.style.display="block";const[i,t]=this.config.canvasSize;this.canvas.width=i,this.canvas.height=t,this.canvas.style.width=i+"px",this.canvas.style.height=t+"px"}this.canvas.style.pointerEvents="none"}createParticles(){this.particles=[];const i=Array.isArray(this.config.particleColor);for(let t=0;t<this.config.particleNumber;t++){let t;if(i){const i=this.config.particleColor;t=i[Math.floor(Math.random()*i.length)]}else t=this.config.particleColor;this.particles.push({x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:2*(Math.random()-.5)*this.config.particleSpeed,vy:2*(Math.random()-.5)*this.config.particleSpeed,size:this.config.particleSize,color:t,originalColor:t,pulse:0,pulseSpeed:.05*Math.random()+.02,trailPositions:[]})}}updateParticles(i){const t=i/16.67;for(const i of this.particles)i.pulse+=i.pulseSpeed*t,i.pulse>2*Math.PI&&(i.pulse=0),this.config.showTrail&&(i.trailPositions.unshift({x:i.x,y:i.y}),i.trailPositions.length>10*this.config.trailIntensity&&(i.trailPositions.length=10*this.config.trailIntensity)),i.x+=i.vx*t,i.y+=i.vy*t,(i.x<0||i.x>this.canvas.width)&&(i.vx*=-1),(i.y<0||i.y>this.canvas.height)&&(i.vy*=-1),i.x=Math.max(0,Math.min(this.canvas.width,i.x)),i.y=Math.max(0,Math.min(this.canvas.height,i.y))}drawTrailEffect(){if(this.config.showTrail){this.ctx.save();for(const i of this.particles){if(i.trailPositions.length<2)continue;this.ctx.beginPath(),this.ctx.moveTo(i.trailPositions[0].x,i.trailPositions[0].y);for(let t=1;t<i.trailPositions.length;t++)this.ctx.lineTo(i.trailPositions[t].x,i.trailPositions[t].y);const t=1.2*i.size;this.ctx.lineWidth=t,this.ctx.lineCap="round",this.ctx.lineJoin="round";const s=i.trailPositions[0],e=i.trailPositions[i.trailPositions.length-1],a=this.ctx.createLinearGradient(s.x,s.y,e.x,e.y),n=this.parseColor(i.color),r=.35;a.addColorStop(0,`rgba(${n.r}, ${n.g}, ${n.b}, ${r})`),a.addColorStop(.3,`rgba(${n.r}, ${n.g}, ${n.b}, ${.6*r})`),a.addColorStop(.7,`rgba(${n.r}, ${n.g}, ${n.b}, ${.2*r})`),a.addColorStop(1,`rgba(${n.r}, ${n.g}, ${n.b}, 0)`),this.ctx.strokeStyle=a,this.ctx.stroke()}this.ctx.restore()}}parseColor(i){if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3]),a:parseFloat(t[4])}}else if(i.startsWith("rgb")){const t=i.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3])}}else if(i.startsWith("#")){let t,s,e,a=i.replace("#","");if(3===a.length)t=parseInt(a[0]+a[0],16),s=parseInt(a[1]+a[1],16),e=parseInt(a[2]+a[2],16);else{if(6!==a.length)return{r:255,g:255,b:255};t=parseInt(a.substring(0,2),16),s=parseInt(a.substring(2,4),16),e=parseInt(a.substring(4,6),16)}return{r:t,g:s,b:e}}return{r:255,g:255,b:255}}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);let i=this.config.canvasBackgroundColor;if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t){const s=t[1],e=t[2],a=t[3];parseFloat(t[4])<1&&(i=`rgb(${s}, ${e}, ${a})`)}}if(this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.drawTrailEffect(),this.config.showLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const s=this.particles[i].x-this.particles[t].x,e=this.particles[i].y-this.particles[t].y,a=Math.sqrt(s*s+e*e);if(a<this.config.linkDistance){const s=this.config.lineOpacity*(1-a/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=s,this.ctx.lineWidth=this.config.lineWidth,this.ctx.beginPath(),this.ctx.moveTo(this.particles[i].x,this.particles[i].y),this.ctx.lineTo(this.particles[t].x,this.particles[t].y),this.ctx.stroke()}}this.ctx.globalAlpha=1;for(const i of this.particles){const t=i.size*(1+.2*Math.sin(i.pulse));this.config.particleBlur>0&&(this.ctx.shadowColor=i.color,this.ctx.shadowBlur=4*this.config.particleBlur),this.ctx.beginPath(),this.ctx.arc(i.x,i.y,t,0,2*Math.PI),this.ctx.fillStyle=i.color,this.ctx.fill(),this.ctx.shadowBlur=0}}updateFPS(){this.frameCount++;const i=Date.now(),t=i-this.lastFpsUpdate;t>=1e3&&(this.fps=Math.round(1e3*this.frameCount/t),this.frameCount=0,this.lastFpsUpdate=i)}animate(){if(!this.isRunning)return;const i=performance.now(),t=i-this.lastFrameTime,s=Math.min(Math.max(t,1),100);this.updateParticles(s),this.drawParticles(),this.updateFPS(),this.lastFrameTime=i,this.animationId=requestAnimationFrame(()=>this.animate())}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.animate())}pause(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}reset(){const i=this.isRunning;i&&this.pause(),this.createParticles(),i?this.start():this.drawParticles()}resize(){if(this.config.isBackground){const i=this.canvas.width,t=this.canvas.height,s=window.innerWidth,e=window.innerHeight;if(this.canvas.width=s,this.canvas.height=e,this.particles.length>0){const a=s/i,n=e/t;for(const i of this.particles)if(i.x*=a,i.y*=n,i.x=Math.max(0,Math.min(s,i.x)),i.y=Math.max(0,Math.min(e,i.y)),(i.x<=0||i.x>=s)&&(i.vx*=-1),(i.y<=0||i.y>=e)&&(i.vy*=-1),this.config.showTrail)for(let t=0;t<i.trailPositions.length;t++){const r=i.trailPositions[t];r.x*=a,r.y*=n,r.x=Math.max(0,Math.min(s,r.x)),r.y=Math.max(0,Math.min(e,r.y))}this.drawParticles()}else this.createParticles(),this.drawParticles()}}destroy(){this.pause(),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}bindEvents(){window.addEventListener("resize",()=>{this.config.isBackground&&(this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resize()},150))}),document.addEventListener("visibilitychange",()=>{document.hidden?(this.wasRunningBeforeHide=this.isRunning,this.isRunning&&this.pause()):(this.wasRunningBeforeHide&&this.start(),this.wasRunningBeforeHide=!1)})}}const s=t;return i.ParticleCanvas=t,i.default=s,Object.defineProperty(i,"__esModule",{value:!0}),i}({});
1
+ var ParticleCanvasPro=function(i){"use strict";class t{constructor(i={}){this.MAX_PARTICLE_NUMBER=800,this.MAX_PARTICLE_SPEED=3,this.MAX_PARTICLE_SIZE=10,this.MAX_LINK_DISTANCE=300,this.MAX_LINE_WIDTH=5,this.MAX_LINE_OPACITY=1,this.MAX_TRAIL_VALUE=1,this.MAX_PARTICLE_BLUR=5,this.MAX_TRAIL_INTENSITY=5;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgb(10, 10, 25)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",particleBlur:void 0!==t.particleBlur?t.particleBlur:2,lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLine:void 0===t.showLine||t.showLine,canvasSize:t.canvasSize||[800,600],showTrail:void 0===t.showTrail||t.showTrail,trailIntensity:t.trailIntensity||2},this.particles=[],this.animationId=null,this.isRunning=!1,this.lastTime=0,this.fps=60,this.fpsInterval=1e3/60,this.then=Date.now(),this.frameCount=0,this.lastFpsUpdate=Date.now(),this.resizeTimer=null,this.wasRunningBeforeHide=!1,this.lastFrameTime=performance.now(),this.init()}validateAndLimitOptions(i){const t=Object.assign({},i);return void 0!==i.particleNumber&&(i.particleNumber>this.MAX_PARTICLE_NUMBER?(console.warn(`Warning: particleNumber (${i.particleNumber}) exceeds maximum allowed value (${this.MAX_PARTICLE_NUMBER}). Using maximum value instead.`),t.particleNumber=this.MAX_PARTICLE_NUMBER):i.particleNumber<1&&(console.warn(`Warning: particleNumber (${i.particleNumber}) is below minimum value (1). Using default value instead.`),t.particleNumber=150)),void 0!==i.particleSpeed&&(i.particleSpeed>this.MAX_PARTICLE_SPEED?(console.warn(`Warning: particleSpeed (${i.particleSpeed}) exceeds maximum allowed value (${this.MAX_PARTICLE_SPEED}). Using maximum value instead.`),t.particleSpeed=this.MAX_PARTICLE_SPEED):i.particleSpeed<0&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0). Using default value instead.`),t.particleSpeed=1)),void 0!==i.particleSize&&(i.particleSize>this.MAX_PARTICLE_SIZE?(console.warn(`Warning: particleSize (${i.particleSize}) exceeds maximum allowed value (${this.MAX_PARTICLE_SIZE}). Using maximum value instead.`),t.particleSize=this.MAX_PARTICLE_SIZE):i.particleSize<1&&(console.warn(`Warning: particleSize (${i.particleSize}) is below minimum value (1). Using default value instead.`),t.particleSize=3)),void 0!==i.particleBlur&&(i.particleBlur>this.MAX_PARTICLE_BLUR?(console.warn(`Warning: particleBlur (${i.particleBlur}) exceeds maximum allowed value (${this.MAX_PARTICLE_BLUR}). Using maximum value instead.`),t.particleBlur=this.MAX_PARTICLE_BLUR):i.particleBlur<0&&(console.warn(`Warning: particleBlur (${i.particleBlur}) is below minimum value (0). Using default value instead.`),t.particleBlur=2)),void 0!==i.linkDistance&&(i.linkDistance>this.MAX_LINK_DISTANCE?(console.warn(`Warning: linkDistance (${i.linkDistance}) exceeds maximum allowed value (${this.MAX_LINK_DISTANCE}). Using maximum value instead.`),t.linkDistance=this.MAX_LINK_DISTANCE):i.linkDistance<10&&(console.warn(`Warning: linkDistance (${i.linkDistance}) is below minimum value (10). Using default value instead.`),t.linkDistance=120)),void 0!==i.lineWidth&&(i.lineWidth>this.MAX_LINE_WIDTH?(console.warn(`Warning: lineWidth (${i.lineWidth}) exceeds maximum allowed value (${this.MAX_LINE_WIDTH}). Using maximum value instead.`),t.lineWidth=this.MAX_LINE_WIDTH):i.lineWidth<0&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0). Using default value instead.`),t.lineWidth=1)),void 0!==i.lineOpacity&&(i.lineOpacity>this.MAX_LINE_OPACITY?(console.warn(`Warning: lineOpacity (${i.lineOpacity}) exceeds maximum allowed value (${this.MAX_LINE_OPACITY}). Using maximum value instead.`),t.lineOpacity=this.MAX_LINE_OPACITY):i.lineOpacity<0&&(console.warn(`Warning: lineOpacity (${i.lineOpacity}) is below minimum value (0). Using default value instead.`),t.lineOpacity=.3)),void 0!==i.trailIntensity&&(i.trailIntensity>this.MAX_TRAIL_INTENSITY?(console.warn(`Warning: trailIntensity (${i.trailIntensity}) exceeds maximum allowed value (${this.MAX_TRAIL_INTENSITY}). Using maximum value instead.`),t.trailIntensity=this.MAX_TRAIL_INTENSITY):i.trailIntensity<1&&(console.warn(`Warning: trailIntensity (${i.trailIntensity}) is below minimum value (1). Using default value instead.`),t.trailIntensity=2)),t}init(){this.canvas=document.createElement("canvas");const i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");if(this.ctx=i,"string"==typeof this.config.canvasContainer){const i=document.querySelector(this.config.canvasContainer);if(!i)throw new Error(`Canvas container not found: ${this.config.canvasContainer}`);this.container=i}else this.container=this.config.canvasContainer;this.container?(this.container.appendChild(this.canvas),this.setupCanvas(),this.createParticles(),this.bindEvents()):console.error("Canvas container not found")}setupCanvas(){if(this.config.isBackground)this.canvas.style.position="fixed",this.canvas.style.top="0",this.canvas.style.left="0",this.canvas.style.width="100%",this.canvas.style.height="100%",this.canvas.style.zIndex="-1",this.canvas.width=window.innerWidth,this.canvas.height=window.innerHeight;else{this.canvas.style.display="block";const[i,t]=this.config.canvasSize;this.canvas.width=i,this.canvas.height=t,this.canvas.style.width=i+"px",this.canvas.style.height=t+"px"}this.canvas.style.pointerEvents="none"}createParticles(){this.particles=[];const i=Array.isArray(this.config.particleColor);for(let t=0;t<this.config.particleNumber;t++){let t;if(i){const i=this.config.particleColor;t=i[Math.floor(Math.random()*i.length)]}else t=this.config.particleColor;this.particles.push({x:Math.random()*this.canvas.width,y:Math.random()*this.canvas.height,vx:2*(Math.random()-.5)*this.config.particleSpeed,vy:2*(Math.random()-.5)*this.config.particleSpeed,size:this.config.particleSize,color:t,originalColor:t,pulse:0,pulseSpeed:.05*Math.random()+.02,trailPositions:[]})}}updateParticles(i){const t=i/16.67;for(const i of this.particles)i.pulse+=i.pulseSpeed*t,i.pulse>2*Math.PI&&(i.pulse=0),this.config.showTrail&&(i.trailPositions.unshift({x:i.x,y:i.y}),i.trailPositions.length>10*this.config.trailIntensity&&(i.trailPositions.length=10*this.config.trailIntensity)),i.x+=i.vx*t,i.y+=i.vy*t,(i.x<0||i.x>this.canvas.width)&&(i.vx*=-1),(i.y<0||i.y>this.canvas.height)&&(i.vy*=-1),i.x=Math.max(0,Math.min(this.canvas.width,i.x)),i.y=Math.max(0,Math.min(this.canvas.height,i.y))}drawTrailEffect(){if(this.config.showTrail){this.ctx.save();for(const i of this.particles){if(i.trailPositions.length<2)continue;this.ctx.beginPath(),this.ctx.moveTo(i.trailPositions[0].x,i.trailPositions[0].y);for(let t=1;t<i.trailPositions.length;t++)this.ctx.lineTo(i.trailPositions[t].x,i.trailPositions[t].y);const t=1.2*i.size;this.ctx.lineWidth=t,this.ctx.lineCap="round",this.ctx.lineJoin="round";const s=i.trailPositions[0],e=i.trailPositions[i.trailPositions.length-1],a=this.ctx.createLinearGradient(s.x,s.y,e.x,e.y),n=this.parseColor(i.color),r=.35;a.addColorStop(0,`rgba(${n.r}, ${n.g}, ${n.b}, ${r})`),a.addColorStop(.3,`rgba(${n.r}, ${n.g}, ${n.b}, ${.6*r})`),a.addColorStop(.7,`rgba(${n.r}, ${n.g}, ${n.b}, ${.2*r})`),a.addColorStop(1,`rgba(${n.r}, ${n.g}, ${n.b}, 0)`),this.ctx.strokeStyle=a,this.ctx.stroke()}this.ctx.restore()}}parseColor(i){if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3]),a:parseFloat(t[4])}}else if(i.startsWith("rgb")){const t=i.match(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);if(t)return{r:parseInt(t[1]),g:parseInt(t[2]),b:parseInt(t[3])}}else if(i.startsWith("#")){let t,s,e,a=i.replace("#","");if(3===a.length)t=parseInt(a[0]+a[0],16),s=parseInt(a[1]+a[1],16),e=parseInt(a[2]+a[2],16);else{if(6!==a.length)return{r:255,g:255,b:255};t=parseInt(a.substring(0,2),16),s=parseInt(a.substring(2,4),16),e=parseInt(a.substring(4,6),16)}return{r:t,g:s,b:e}}return{r:255,g:255,b:255}}drawParticles(){this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);let i=this.config.canvasBackgroundColor;if(i.startsWith("rgba")){const t=i.match(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d.]+)\s*\)/);if(t){const s=t[1],e=t[2],a=t[3];parseFloat(t[4])<1&&(i=`rgb(${s}, ${e}, ${a})`)}}if(this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.drawTrailEffect(),this.config.showLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const s=this.particles[i].x-this.particles[t].x,e=this.particles[i].y-this.particles[t].y,a=Math.sqrt(s*s+e*e);if(a<this.config.linkDistance){const s=this.config.lineOpacity*(1-a/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=s,this.ctx.lineWidth=this.config.lineWidth,this.ctx.beginPath(),this.ctx.moveTo(this.particles[i].x,this.particles[i].y),this.ctx.lineTo(this.particles[t].x,this.particles[t].y),this.ctx.stroke()}}this.ctx.globalAlpha=1;for(const i of this.particles){const t=i.size*(1+.2*Math.sin(i.pulse));this.config.particleBlur>0&&(this.ctx.shadowColor=i.color,this.ctx.shadowBlur=4*this.config.particleBlur),this.ctx.beginPath(),this.ctx.arc(i.x,i.y,t,0,2*Math.PI),this.ctx.fillStyle=i.color,this.ctx.fill(),this.ctx.shadowBlur=0}}updateFPS(){this.frameCount++;const i=Date.now(),t=i-this.lastFpsUpdate;t>=1e3&&(this.fps=Math.round(1e3*this.frameCount/t),this.frameCount=0,this.lastFpsUpdate=i)}animate(){if(!this.isRunning)return;const i=performance.now(),t=i-this.lastFrameTime,s=Math.min(Math.max(t,1),100);this.updateParticles(s),this.drawParticles(),this.updateFPS(),this.lastFrameTime=i,this.animationId=requestAnimationFrame(()=>this.animate())}start(){this.isRunning||(this.isRunning=!0,this.lastFrameTime=performance.now(),this.animate())}stop(){this.isRunning=!1,this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null)}reset(){const i=this.isRunning;i&&this.stop(),this.createParticles(),i?this.start():this.drawParticles()}resize(){if(this.config.isBackground){const i=this.canvas.width,t=this.canvas.height,s=window.innerWidth,e=window.innerHeight;if(this.canvas.width=s,this.canvas.height=e,this.particles.length>0){const a=s/i,n=e/t;for(const i of this.particles)if(i.x*=a,i.y*=n,i.x=Math.max(0,Math.min(s,i.x)),i.y=Math.max(0,Math.min(e,i.y)),(i.x<=0||i.x>=s)&&(i.vx*=-1),(i.y<=0||i.y>=e)&&(i.vy*=-1),this.config.showTrail)for(let t=0;t<i.trailPositions.length;t++){const r=i.trailPositions[t];r.x*=a,r.y*=n,r.x=Math.max(0,Math.min(s,r.x)),r.y=Math.max(0,Math.min(e,r.y))}this.drawParticles()}else this.createParticles(),this.drawParticles()}}destroy(){this.stop(),this.canvas&&this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas)}bindEvents(){window.addEventListener("resize",()=>{this.config.isBackground&&(this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.resize()},150))}),document.addEventListener("visibilitychange",()=>{document.hidden?(this.wasRunningBeforeHide=this.isRunning,this.isRunning&&this.stop()):(this.wasRunningBeforeHide&&this.start(),this.wasRunningBeforeHide=!1)})}}const s=t;return i.ParticleCanvas=t,i.default=s,Object.defineProperty(i,"__esModule",{value:!0}),i}({});
@@ -94,7 +94,7 @@ declare class ParticleCanvas {
94
94
  /**
95
95
  * 暂停粒子动画
96
96
  */
97
- pause(): void;
97
+ stop(): void;
98
98
  /**
99
99
  * 重置粒子系统
100
100
  * 重新创建粒子并开始动画
@@ -49,7 +49,7 @@ export interface ParticleCanvasConfig {
49
49
  export declare class ParticleCanvas {
50
50
  constructor(options?: ParticleCanvasOptions);
51
51
  start(): void;
52
- pause(): void;
52
+ stop(): void;
53
53
  reset(): void;
54
54
  resize(): void;
55
55
  destroy(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "particle-canvas-pro",
3
- "version": "1.4.4",
3
+ "version": "1.4.6",
4
4
  "description": "🚀 🚀 一款基于requestAnimationFrame的高性能Canvas粒子系统,专为 Web 场景提供流畅、可配置的视觉动效方案,支持全屏背景与独立画布,提供实时控制、丰富视觉效果与流畅交互体验。",
5
5
  "main": "dist/bundle.cjs.js",
6
6
  "module": "dist/bundle.esm.js",