particle-canvas-pro 1.2.6 → 1.3.1
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 +9 -8
- package/dist/bundle.cjs.js +1 -1
- package/dist/bundle.esm.js +1 -1
- package/dist/bundle.js +1 -1
- package/dist/types/ParticleCanvas.d.ts +13 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/types.d.ts +21 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,21 +77,22 @@ particleSystem.start();
|
|
|
77
77
|
# 参数配置
|
|
78
78
|
|
|
79
79
|
| 参数名 | 说明 | 类型 | 取值范围 | 默认值 |
|
|
80
|
-
|
|
81
|
-
| canvasContainer | 画布容器元素或选择器
|
|
80
|
+
|------------------------|---------------------------------------|--------------------------|-----------------------------|---------------------------|
|
|
81
|
+
| canvasContainer | 画布容器元素或选择器 | `string` / `HTMLElement` | - | `document.body` |
|
|
82
|
+
| canvasBackgroundColor | 画布背景颜色 | `string` | - | `rgb(10, 10, 25)` |
|
|
83
|
+
| canvasSize | 画布尺寸(非背景模式) | `[number, number]` | - | [800, 600] |
|
|
82
84
|
| isBackground | 是否作为页面背景 | `boolean` | `true` / `false` | `true` |
|
|
83
|
-
| canvasBackgroundColor | 画布背景颜色 | `string` | - | `rgba(10, 10, 25, 1)` |
|
|
84
85
|
| particleNumber | 粒子数量 | `number` | 1-800 | 150 |
|
|
85
|
-
| particleSpeed | 粒子运动速度 | `number` | 0
|
|
86
|
+
| particleSpeed | 粒子运动速度 | `number` | 0-3 | 1 |
|
|
86
87
|
| particleSize | 粒子大小(像素) | `number` | 1-10 | 5 |
|
|
87
88
|
| particleColor | 粒子颜色(单色或多色) | `string` / `string[]` | - | `rgba(156, 74, 255, 0.6)` |
|
|
88
|
-
|
|
|
89
|
+
| showTrail | 是否显示粒子轨迹效果 | `boolean` | `true` / `false` | `true` |
|
|
90
|
+
| trailIntensity | 粒子轨迹效果强度 | `number` | 0-5 | 2 |
|
|
91
|
+
| showLine | 是否显示粒子连线 | `boolean` | `true` / `false` | `true` |
|
|
92
|
+
| lineWidth | 连线宽度(像素) | `number` | 0-5 | 1 |
|
|
89
93
|
| lineColor | 连线颜色 | `string` | - | `#ffffff` |
|
|
90
94
|
| lineOpacity | 连线透明度 | `number` | 0-1 | 0.3 |
|
|
91
95
|
| linkDistance | 连线距离(像素) | `number` | 10-300 | 120 |
|
|
92
|
-
| showLinkLine | 是否显示连线 | `boolean` | `true` / `false` | `true` |
|
|
93
|
-
| canvasSize | 画布尺寸(非背景模式) | `[number, number]` | - | [800, 600] |
|
|
94
|
-
| trailValue | 轨迹效果强度 | `number` | 0-1 | 0.2 |
|
|
95
96
|
|
|
96
97
|
<br>
|
|
97
98
|
|
package/dist/bundle.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const i=class{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;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgba(10, 10, 25, 1)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLinkLine:void 0===t.showLinkLine||t.showLinkLine,canvasSize:t.canvasSize||[800,600],trailValue:t.trailValue||.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 minimum value instead.`),t.particleNumber=1)),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<.1&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0.1). Using minimum 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 minimum value instead.`),t.particleSize=1)),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 minimum value instead.`),t.linkDistance=10)),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<.1&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0.1). Using minimum 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 minimum value instead.`),t.lineOpacity=0)),void 0!==i.trailValue&&(i.trailValue>this.MAX_TRAIL_VALUE?(console.warn(`Warning: trailValue (${i.trailValue}) exceeds maximum allowed value (${this.MAX_TRAIL_VALUE}). Using maximum value instead.`),t.trailValue=this.MAX_TRAIL_VALUE):i.trailValue<0&&(console.warn(`Warning: trailValue (${i.trailValue}) is below minimum value (0). Using minimum value instead.`),t.trailValue=0)),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})}}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),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))}drawParticles(){if(this.config.trailValue>0){let i=this.config.canvasBackgroundColor;if(i.startsWith("#")){const t=parseInt(i.slice(1,3),16),e=parseInt(i.slice(3,5),16),a=parseInt(i.slice(5,7),16);i=`rgba(${t}, ${e}, ${a}, ${this.config.trailValue})`}else if(i.startsWith("rgb("))i=i.replace("rgb(","rgba(").replace(")",`, ${this.config.trailValue})`);else if(i.startsWith("rgba(")){const t=i.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);if(t){const e=parseFloat(t[4])*this.config.trailValue;i=`rgba(${t[1]}, ${t[2]}, ${t[3]}, ${e})`}}this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}else this.ctx.fillStyle=this.config.canvasBackgroundColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height);if(this.config.showLinkLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const e=this.particles[i].x-this.particles[t].x,a=this.particles[i].y-this.particles[t].y,s=Math.sqrt(e*e+a*a);if(s<this.config.linkDistance){const e=this.config.lineOpacity*(1-s/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=e,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.ctx.shadowColor=i.color,this.ctx.shadowBlur=10,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,e=Math.min(Math.max(t,1),100);this.updateParticles(e),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,e=window.innerWidth,a=window.innerHeight;if(this.canvas.width=e,this.canvas.height=a,this.particles.length>0){const s=e/i,n=a/t;for(const i of this.particles)i.x*=s,i.y*=n,i.x=Math.max(0,Math.min(e,i.x)),i.y=Math.max(0,Math.min(a,i.y)),(i.x<=0||i.x>=e)&&(i.vx*=-1),(i.y<=0||i.y>=a)&&(i.vy*=-1);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)})}};module.exports=i;
|
|
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;
|
package/dist/bundle.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const i=class{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;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgba(10, 10, 25, 1)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLinkLine:void 0===t.showLinkLine||t.showLinkLine,canvasSize:t.canvasSize||[800,600],trailValue:t.trailValue||.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 minimum value instead.`),t.particleNumber=1)),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<.1&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0.1). Using minimum 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 minimum value instead.`),t.particleSize=1)),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 minimum value instead.`),t.linkDistance=10)),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<.1&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0.1). Using minimum 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 minimum value instead.`),t.lineOpacity=0)),void 0!==i.trailValue&&(i.trailValue>this.MAX_TRAIL_VALUE?(console.warn(`Warning: trailValue (${i.trailValue}) exceeds maximum allowed value (${this.MAX_TRAIL_VALUE}). Using maximum value instead.`),t.trailValue=this.MAX_TRAIL_VALUE):i.trailValue<0&&(console.warn(`Warning: trailValue (${i.trailValue}) is below minimum value (0). Using minimum value instead.`),t.trailValue=0)),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})}}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),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))}drawParticles(){if(this.config.trailValue>0){let i=this.config.canvasBackgroundColor;if(i.startsWith("#")){const t=parseInt(i.slice(1,3),16),e=parseInt(i.slice(3,5),16),a=parseInt(i.slice(5,7),16);i=`rgba(${t}, ${e}, ${a}, ${this.config.trailValue})`}else if(i.startsWith("rgb("))i=i.replace("rgb(","rgba(").replace(")",`, ${this.config.trailValue})`);else if(i.startsWith("rgba(")){const t=i.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);if(t){const e=parseFloat(t[4])*this.config.trailValue;i=`rgba(${t[1]}, ${t[2]}, ${t[3]}, ${e})`}}this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}else this.ctx.fillStyle=this.config.canvasBackgroundColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height);if(this.config.showLinkLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const e=this.particles[i].x-this.particles[t].x,a=this.particles[i].y-this.particles[t].y,s=Math.sqrt(e*e+a*a);if(s<this.config.linkDistance){const e=this.config.lineOpacity*(1-s/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=e,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.ctx.shadowColor=i.color,this.ctx.shadowBlur=10,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,e=Math.min(Math.max(t,1),100);this.updateParticles(e),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,e=window.innerWidth,a=window.innerHeight;if(this.canvas.width=e,this.canvas.height=a,this.particles.length>0){const s=e/i,n=a/t;for(const i of this.particles)i.x*=s,i.y*=n,i.x=Math.max(0,Math.min(e,i.x)),i.y=Math.max(0,Math.min(a,i.y)),(i.x<=0||i.x>=e)&&(i.vx*=-1),(i.y<=0||i.y>=a)&&(i.vy*=-1);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)})}};export{i 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())}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};
|
package/dist/bundle.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var ParticleCanvasPro=function(){"use strict";return class{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;const t=this.validateAndLimitOptions(i);this.config={canvasContainer:t.canvasContainer||document.body,isBackground:void 0===t.isBackground||t.isBackground,canvasBackgroundColor:t.canvasBackgroundColor||"rgba(10, 10, 25, 1)",particleNumber:t.particleNumber||150,particleSpeed:t.particleSpeed||1,particleSize:t.particleSize||5,particleColor:t.particleColor||"rgba(156, 74, 255, 0.6)",lineWidth:t.lineWidth||1,lineColor:t.lineColor||"#ffffff",lineOpacity:t.lineOpacity||.3,linkDistance:t.linkDistance||120,showLinkLine:void 0===t.showLinkLine||t.showLinkLine,canvasSize:t.canvasSize||[800,600],trailValue:t.trailValue||.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 minimum value instead.`),t.particleNumber=1)),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<.1&&(console.warn(`Warning: particleSpeed (${i.particleSpeed}) is below minimum value (0.1). Using minimum 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 minimum value instead.`),t.particleSize=1)),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 minimum value instead.`),t.linkDistance=10)),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<.1&&(console.warn(`Warning: lineWidth (${i.lineWidth}) is below minimum value (0.1). Using minimum 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 minimum value instead.`),t.lineOpacity=0)),void 0!==i.trailValue&&(i.trailValue>this.MAX_TRAIL_VALUE?(console.warn(`Warning: trailValue (${i.trailValue}) exceeds maximum allowed value (${this.MAX_TRAIL_VALUE}). Using maximum value instead.`),t.trailValue=this.MAX_TRAIL_VALUE):i.trailValue<0&&(console.warn(`Warning: trailValue (${i.trailValue}) is below minimum value (0). Using minimum value instead.`),t.trailValue=0)),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})}}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),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))}drawParticles(){if(this.config.trailValue>0){let i=this.config.canvasBackgroundColor;if(i.startsWith("#")){const t=parseInt(i.slice(1,3),16),e=parseInt(i.slice(3,5),16),a=parseInt(i.slice(5,7),16);i=`rgba(${t}, ${e}, ${a}, ${this.config.trailValue})`}else if(i.startsWith("rgb("))i=i.replace("rgb(","rgba(").replace(")",`, ${this.config.trailValue})`);else if(i.startsWith("rgba(")){const t=i.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)\)/);if(t){const e=parseFloat(t[4])*this.config.trailValue;i=`rgba(${t[1]}, ${t[2]}, ${t[3]}, ${e})`}}this.ctx.fillStyle=i,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height)}else this.ctx.fillStyle=this.config.canvasBackgroundColor,this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height);if(this.config.showLinkLine)for(let i=0;i<this.particles.length;i++)for(let t=i+1;t<this.particles.length;t++){const e=this.particles[i].x-this.particles[t].x,a=this.particles[i].y-this.particles[t].y,s=Math.sqrt(e*e+a*a);if(s<this.config.linkDistance){const e=this.config.lineOpacity*(1-s/this.config.linkDistance);this.ctx.strokeStyle=this.config.lineColor,this.ctx.globalAlpha=e,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.ctx.shadowColor=i.color,this.ctx.shadowBlur=10,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,e=Math.min(Math.max(t,1),100);this.updateParticles(e),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,e=window.innerWidth,a=window.innerHeight;if(this.canvas.width=e,this.canvas.height=a,this.particles.length>0){const s=e/i,n=a/t;for(const i of this.particles)i.x*=s,i.y*=n,i.x=Math.max(0,Math.min(e,i.x)),i.y=Math.max(0,Math.min(a,i.y)),(i.x<=0||i.x>=e)&&(i.vx*=-1),(i.y<=0||i.y>=a)&&(i.vy*=-1);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)})}}}();
|
|
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}({});
|
|
@@ -26,6 +26,8 @@ declare class ParticleCanvas {
|
|
|
26
26
|
private readonly MAX_LINE_WIDTH;
|
|
27
27
|
private readonly MAX_LINE_OPACITY;
|
|
28
28
|
private readonly MAX_TRAIL_VALUE;
|
|
29
|
+
private readonly MAX_PARTICLE_BLUR;
|
|
30
|
+
private readonly MAX_TRAIL_INTENSITY;
|
|
29
31
|
private lastFrameTime;
|
|
30
32
|
/**
|
|
31
33
|
* 初始化配置
|
|
@@ -59,6 +61,17 @@ declare class ParticleCanvas {
|
|
|
59
61
|
* @param deltaTime 时间增量(毫秒)
|
|
60
62
|
*/
|
|
61
63
|
private updateParticles;
|
|
64
|
+
/**
|
|
65
|
+
* 绘制粒子轨迹效果
|
|
66
|
+
* 在粒子后面绘制自然的光影拖尾效果
|
|
67
|
+
*/
|
|
68
|
+
private drawTrailEffect;
|
|
69
|
+
/**
|
|
70
|
+
* 解析颜色字符串为RGB对象
|
|
71
|
+
* @param colorStr 颜色字符串
|
|
72
|
+
* @returns RGB对象
|
|
73
|
+
*/
|
|
74
|
+
private parseColor;
|
|
62
75
|
/**
|
|
63
76
|
* 绘制粒子和连线
|
|
64
77
|
* 在画布上渲染粒子系统
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/types.d.ts
CHANGED
|
@@ -8,36 +8,49 @@ export interface Particle {
|
|
|
8
8
|
originalColor: string;
|
|
9
9
|
pulse: number;
|
|
10
10
|
pulseSpeed: number;
|
|
11
|
+
trailPositions: any[];
|
|
11
12
|
}
|
|
12
13
|
export interface ParticleCanvasOptions {
|
|
13
14
|
canvasContainer?: HTMLElement | string;
|
|
14
|
-
|
|
15
|
+
canvasSize?: [number, number];
|
|
15
16
|
canvasBackgroundColor?: string;
|
|
17
|
+
isBackground?: boolean;
|
|
16
18
|
particleNumber?: number;
|
|
17
19
|
particleSpeed?: number;
|
|
18
20
|
particleSize?: number;
|
|
19
21
|
particleColor?: string | string[];
|
|
22
|
+
particleBlur?: number;
|
|
23
|
+
showTrail?: boolean;
|
|
24
|
+
trailIntensity?: number;
|
|
25
|
+
showLine?: boolean;
|
|
20
26
|
lineWidth?: number;
|
|
21
27
|
lineColor?: string;
|
|
22
28
|
lineOpacity?: number;
|
|
23
29
|
linkDistance?: number;
|
|
24
|
-
showLinkLine?: boolean;
|
|
25
|
-
canvasSize?: [number, number];
|
|
26
|
-
trailValue?: number;
|
|
27
30
|
}
|
|
28
31
|
export interface ParticleCanvasConfig {
|
|
29
32
|
canvasContainer: HTMLElement | string;
|
|
30
|
-
|
|
33
|
+
canvasSize: [number, number];
|
|
31
34
|
canvasBackgroundColor: string;
|
|
35
|
+
isBackground: boolean;
|
|
32
36
|
particleNumber: number;
|
|
33
37
|
particleSpeed: number;
|
|
34
38
|
particleSize: number;
|
|
35
39
|
particleColor: string | string[];
|
|
40
|
+
particleBlur: number;
|
|
41
|
+
showTrail: boolean;
|
|
42
|
+
trailIntensity: number;
|
|
43
|
+
showLine: boolean;
|
|
36
44
|
lineWidth: number;
|
|
37
45
|
lineColor: string;
|
|
38
46
|
lineOpacity: number;
|
|
39
47
|
linkDistance: number;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
}
|
|
49
|
+
export declare class ParticleCanvas {
|
|
50
|
+
constructor(options?: ParticleCanvasOptions);
|
|
51
|
+
start(): void;
|
|
52
|
+
pause(): void;
|
|
53
|
+
reset(): void;
|
|
54
|
+
resize(): void;
|
|
55
|
+
destroy(): void;
|
|
43
56
|
}
|
package/package.json
CHANGED