(function(global){
'use strict';
if(typeof gsap!=='undefined'&&typeof ScrollTrigger!=='undefined'){
gsap.registerPlugin(ScrollTrigger);
}
const randomFrom=(arr)=> arr[Math.floor(Math.random() * arr.length)];
const randomRange=(min, max)=> Math.random() * (max - min) + min;
const clamp=(v, lo, hi)=> Math.min(hi, Math.max(lo, v));
const lerp=(a, b, t)=> a + (b - a) * t;
const dist=(x1, y1, x2, y2)=> Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
const AUTUMN_COLORS=['#c0392b', '#e67e22', '#f1c40f', '#d35400', '#e74c3c', '#f39c12'];
const EMOJIS=['🎉', '🎊', '🥳', '🎈', '🎁', '✨', '🌟', '⭐', '🔥', '❤️'];
const MATRIX_CHARS='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()=+<>?/{}[]|';
const GEOMETRIC_SHAPES=['circle', 'square', 'triangle', 'hexagon'];
function hexToRgb(hex){
hex=hex.replace('#', '');
if(hex.length===3) hex=hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
const n=parseInt(hex, 16);
return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };}
function lerpColor(c1, c2, t){
const a=hexToRgb(c1), b=hexToRgb(c2);
const r=Math.round(lerp(a.r, b.r, t));
const g=Math.round(lerp(a.g, b.g, t));
const bl=Math.round(lerp(a.b, b.b, t));
return 'rgb(' + r + ',' + g + ',' + bl + ')';
}
function randomColor(c1, c2){
return lerpColor(c1, c2, Math.random());
}
function randomColorFromArray(arr){
if(!arr||arr.length===0) return '#ffffff';
if(arr.length===1) return arr[0];
var i=Math.floor(Math.random() * arr.length);
var j=Math.floor(Math.random() * arr.length);
return lerpColor(arr[i], arr[j], Math.random());
}
function createEl(tag, styles, parent){
const el=document.createElement(tag);
Object.assign(el.style, styles);
if(parent) parent.appendChild(el);
return el;
}
function createSVG(parent, w, h){
const ns='http://www.w3.org/2000/svg';
const svg=document.createElementNS(ns, 'svg');
svg.setAttribute('width', w);
svg.setAttribute('height', h);
svg.style.cssText='position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;';
parent.appendChild(svg);
return svg;
}
function createSVGLine(svg){
const ns='http://www.w3.org/2000/svg';
const line=document.createElementNS(ns, 'line');
svg.appendChild(line);
return line;
}
class DnxteParticleEngine {
constructor(element, options){
if(!element) return;
this.element=element;
this._intervals=[];
this._rafs=[];
this._listeners=[];
this._timelines=[];
this._tweens=[];
this._particles=[];
this._destroyed=false;
this._mouseX=-9999;
this._mouseY=-9999;
this._mouseInside=false;
this._paused=false;
const pos=getComputedStyle(element).position;
if(pos==='static') element.style.position='relative';
var defaults={
type: 'snowfall',
count: 40,
speed: 1,
color1: '#00d4aa',
color2: '#7c3aed',
color3: '',
color4: '',
size: 1,
opacity: 0.8,
trigger: 'always',
interactive: false,
effectWidth: 100,
glow: false,
glowIntensity: 1,
wind: 0,
windStrength: 1,
connectionDistance: 150,
burstInterval: 2000,
forceStrength: 1,
forceRadius: 150
};
var data=this._parseDataAttrs(element);
this.opts=Object.assign({}, defaults, data, options||{});
this.opts.count=parseInt(this.opts.count, 10)||40;
this.opts.speed=parseFloat(this.opts.speed)||1;
this.opts.size=parseFloat(this.opts.size)||1;
this.opts.opacity=parseFloat(this.opts.opacity);
if(isNaN(this.opts.opacity)) this.opts.opacity=0.8;
this.opts.wind=parseFloat(this.opts.wind)||0;
this.opts.windStrength=parseFloat(this.opts.windStrength)||1;
this.opts.connectionDistance=parseFloat(this.opts.connectionDistance)||150;
this.opts.burstInterval=parseInt(this.opts.burstInterval, 10)||2000;
this.opts.forceStrength=parseFloat(this.opts.forceStrength)||1;
this.opts.forceRadius=parseFloat(this.opts.forceRadius)||150;
this.opts.glowIntensity=parseFloat(this.opts.glowIntensity)||1;
this.opts.effectWidth=parseInt(this.opts.effectWidth, 10)||100;
if(typeof this.opts.interactive==='string') this.opts.interactive=this.opts.interactive==='true';
if(typeof this.opts.glow==='string') this.opts.glow=this.opts.glow==='true';
this.colors=[this.opts.color1, this.opts.color2];
if(this.opts.color3) this.colors.push(this.opts.color3);
if(this.opts.color4) this.colors.push(this.opts.color4);
var ew=clamp(this.opts.effectWidth, 10, 100);
var containerStyles={
position: 'absolute',
top: '0', bottom: '0',
overflow: 'hidden',
pointerEvents: 'none',
zIndex: '1'
};
if(ew < 100){
containerStyles.left=((100 - ew) / 2) + '%';
containerStyles.width=ew + '%';
}else{
containerStyles.left='0';
containerStyles.right='0';
}
this.container=createEl('div', containerStyles, element);
this.container.classList.add('dnxte-particle-container');
var isInteractiveType=this._isInteractiveEffect(this.opts.type);
if(isInteractiveType||this.opts.interactive){
this.container.style.pointerEvents='auto';
}
this._onMouseMove=this._onMouseMove.bind(this);
this._onMouseLeave=this._onMouseLeave.bind(this);
if(isInteractiveType||this.opts.interactive){
var section=element.closest('section')||element;
section.addEventListener('mousemove', this._onMouseMove);
section.addEventListener('mouseleave', this._onMouseLeave);
this._listeners.push([section, 'mousemove', this._onMouseMove]);
this._listeners.push([section, 'mouseleave', this._onMouseLeave]);
}
this._handleTrigger();
}
_parseDataAttrs(el){
var map={
'particle-type': 'type',
'particle-count': 'count',
'particle-speed': 'speed',
'particle-color1': 'color1',
'particle-color2': 'color2',
'particle-color3': 'color3',
'particle-color4': 'color4',
'particle-size': 'size',
'particle-opacity': 'opacity',
'particle-trigger': 'trigger',
'particle-interactive': 'interactive',
'particle-effect-width': 'effectWidth',
'particle-glow': 'glow',
'particle-glow-intensity': 'glowIntensity',
'particle-wind': 'wind',
'particle-wind-strength': 'windStrength',
'particle-connection-distance': 'connectionDistance',
'particle-burst-interval': 'burstInterval',
'particle-force-strength': 'forceStrength',
'particle-force-radius': 'forceRadius'
};
var out={};
for (var key in map){
var v=el.dataset[this._camelCase(key)];
if(v!==undefined) out[map[key]]=v;
}
return out;
}
_camelCase(str){
return str.replace(/-([a-z])/g, function(m, c){ return c.toUpperCase(); });
}
_isInteractiveEffect(type){
return [
'mouse-attract', 'mouse-repel', 'mouse-trail', 'hover-burst',
'swarm', 'gravity-well', 'connection-web', 'ripple',
'orbit-cursor', 'color-wave'
].indexOf(type)!==-1;
}
_onMouseMove(e){
var rect=this.container.getBoundingClientRect();
this._mouseX=e.clientX - rect.left;
this._mouseY=e.clientY - rect.top;
this._mouseInside=true;
}
_onMouseLeave(){
this._mouseInside=false;
}
_w(){ return this.container.offsetWidth||this.element.offsetWidth||800; }
_h(){ return this.container.offsetHeight||this.element.offsetHeight||600; }
_applyGlow(el, color){
if(this.opts.glow){
var intensity=this.opts.glowIntensity;
var blur=8 * intensity;
var spread=4 * intensity;
el.style.boxShadow='0 0 ' + blur + 'px ' + spread + 'px ' + color;
}}
_applyTextGlow(el, color){
if(this.opts.glow){
var intensity=this.opts.glowIntensity;
var blur=8 * intensity;
el.style.textShadow='0 0 ' + blur + 'px ' + color;
}}
_windOffset(duration){
return this.opts.wind * this.opts.windStrength * 30 * duration;
}
_handleTrigger(){
var self=this;
this._effectActive=false;
if(this.opts.trigger==='always'){
this._effectActive=true;
this._paused=false;
this._initEffect();
return;
}
if(this.opts.trigger==='scroll'){
this._paused=true;
var ST=(typeof ScrollTrigger!=='undefined') ? ScrollTrigger:(typeof gsap!=='undefined'&&gsap.ScrollTrigger) ? gsap.ScrollTrigger:null;
if(ST){
this._scrollTrigger=ST.create({
trigger: this.element,
start: 'top 80%',
end: 'bottom 20%',
onEnter:     function(){ self._startEffect(); },
onLeave:     function(){ self._stopEffect(); },
onEnterBack: function(){ self._startEffect(); },
onLeaveBack: function(){ self._stopEffect(); }});
}else if(typeof IntersectionObserver!=='undefined'){
this._observer=new IntersectionObserver(function(entries){
entries.forEach(function(entry){
if(entry.isIntersecting){
self._startEffect();
}else{
self._stopEffect();
}});
}, { threshold: 0.2 });
this._observer.observe(this.element);
}
return;
}
if(this.opts.trigger==='hover'){
this._paused=true;
var onEnter=function(){ self._startEffect(); };
var onLeave=function(){ self._stopEffect(); };
this.element.addEventListener('mouseenter', onEnter);
this.element.addEventListener('mouseleave', onLeave);
this._listeners.push([this.element, 'mouseenter', onEnter]);
this._listeners.push([this.element, 'mouseleave', onLeave]);
return;
}
this._effectActive=true;
this._paused=false;
this._initEffect();
}
_startEffect(){
if(this._effectActive) return;
this._effectActive=true;
this._paused=false;
this._initEffect();
}
_stopEffect(){
if(!this._effectActive) return;
this._effectActive=false;
this._paused=true;
for (var i=0; i < this._intervals.length; i++) clearInterval(this._intervals[i]);
this._intervals=[];
for (var j=0; j < this._rafs.length; j++) cancelAnimationFrame(this._rafs[j]);
this._rafs=[];
for (var k=0; k < this._tweens.length; k++){
if(this._tweens[k]&&this._tweens[k].kill) this._tweens[k].kill();
}
this._tweens=[];
for (var l=0; l < this._timelines.length; l++){
if(this._timelines[l]&&this._timelines[l].kill) this._timelines[l].kill();
}
this._timelines=[];
while (this.container.firstChild){
this.container.removeChild(this.container.firstChild);
}
this._particles=[];
}
_pauseAll(){
this._tweens.forEach(function(t){ if(t.pause) t.pause(); });
this._timelines.forEach(function(t){ if(t.pause) t.pause(); });
}
_resumeAll(){
this._tweens.forEach(function(t){ if(t.resume) t.resume(); });
this._timelines.forEach(function(t){ if(t.resume) t.resume(); });
}
_addInterval(id){ this._intervals.push(id); return id; }
_addRaf(id){ this._rafs.push(id); return id; }
_addTween(t){ this._tweens.push(t); return t; }
_addTimeline(t){ this._timelines.push(t); return t; }
_initEffect(){
var map={
'confetti':         '_initConfetti',
'fireworks':        '_initFireworks',
'streamers':        '_initStreamers',
'balloons':         '_initBalloons',
'champagne':        '_initChampagne',
'glitter':          '_initGlitter',
'starburst':        '_initStarburst',
'emoji':            '_initEmoji',
'snowfall':         '_initSnowfall',
'fireflies':        '_initFireflies',
'cherry-blossoms':  '_initCherryBlossoms',
'rain':             '_initRain',
'leaves':           '_initLeaves',
'bubbles':          '_initBubbles',
'galaxy':           '_initGalaxy',
'starfield':        '_initStarfield',
'nebula':           '_initNebula',
'comets':           '_initComets',
'matrix':           '_initMatrix',
'network':          '_initNetwork',
'dna':              '_initDna',
'wave':             '_initWave',
'magnetic':         '_initMagnetic',
'aurora':           '_initAurora',
'geometric':        '_initGeometric',
'pulse-rings':      '_initPulseRings',
'vortex':           '_initVortex',
'sparks':           '_initSparks',
'dust':             '_initDust',
'blobs':            '_initBlobs',
'mouse-attract':    '_initMouseAttract',
'mouse-repel':      '_initMouseRepel',
'mouse-trail':      '_initMouseTrail',
'hover-burst':      '_initHoverBurst',
'swarm':            '_initSwarm',
'gravity-well':     '_initGravityWell',
'connection-web':   '_initConnectionWeb',
'ripple':           '_initRipple',
'orbit-cursor':     '_initOrbitCursor',
'color-wave':       '_initColorWave'
};
var fn=map[this.opts.type];
if(fn&&typeof this[fn]==='function'){
this[fn]();
}else{
this._initSnowfall();
}}
_initConfetti(){
var self=this;
var burst=function(){
var w=self._w(), h=self._h();
for (var i=0; i < self.opts.count; i++){
var s=randomRange(6, 12) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: s + 'px',
height: s * randomRange(0.4, 1) + 'px',
backgroundColor: color,
borderRadius: Math.random() > 0.5 ? '2px':'50%',
left: w / 2 + 'px',
top: h / 2 + 'px',
opacity: '0',
zIndex: '2'
}, self.container);
self._applyGlow(el, color);
var angle=randomRange(0, Math.PI * 2);
var radius=randomRange(100, Math.max(w, h) * 0.6);
var dur=randomRange(1.5, 3) / self.opts.speed;
var tl=gsap.timeline();
self._addTimeline(tl);
tl.set(el, { opacity: self.opts.opacity, scale: 0 });
tl.to(el, {
x: Math.cos(angle) * radius + self._windOffset(dur),
y: Math.sin(angle) * radius + randomRange(50, 150),
rotation: randomRange(-720, 720),
scale: 1,
opacity: 0,
duration: dur,
ease: 'power2.out',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }});
}};
burst();
this._addInterval(setInterval(burst, this.opts.burstInterval));
}
_initFireworks(){
var self=this;
var launchOne=function(){
var w=self._w(), h=self._h();
var startX=randomRange(w * 0.2, w * 0.8);
var peakY=randomRange(h * 0.1, h * 0.4);
var rocket=createEl('div', {
position: 'absolute',
width: 4 * self.opts.size + 'px',
height: 12 * self.opts.size + 'px',
backgroundColor: self.opts.color1,
borderRadius: '2px',
left: startX + 'px',
top: h + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(rocket, self.opts.color1);
var dur=randomRange(0.6, 1) / self.opts.speed;
var tl=gsap.timeline();
self._addTimeline(tl);
tl.to(rocket, {
y: -(h - peakY),
duration: dur,
ease: 'power2.in',
onComplete: function(){
if(rocket.parentNode) rocket.parentNode.removeChild(rocket);
var count=Math.floor(self.opts.count * 0.6);
for (var i=0; i < count; i++){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomColorFromArray(self.colors);
var spark=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: startX + 'px',
top: peakY + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(spark, color);
var angle=randomRange(0, Math.PI * 2);
var r=randomRange(40, 150) * self.opts.size;
var d2=randomRange(0.8, 1.5) / self.opts.speed;
self._addTween(gsap.to(spark, {
x: Math.cos(angle) * r,
y: Math.sin(angle) * r + 60,
opacity: 0,
scale: 0.2,
duration: d2,
ease: 'power3.out',
onComplete: function(){ if(spark.parentNode) spark.parentNode.removeChild(spark); }}));
}}
});
};
launchOne();
this._addInterval(setInterval(launchOne, this.opts.burstInterval));
}
_initStreamers(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(idx){
var color=randomColorFromArray(self.colors);
var sw=randomRange(4, 8) * self.opts.size;
var sh=randomRange(40, 80) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: sw + 'px',
height: sh + 'px',
backgroundColor: color,
borderRadius: sw + 'px',
left: randomRange(0, w) + 'px',
top: -sh + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
var dur=randomRange(3, 6) / self.opts.speed;
var delay=randomRange(0, 3);
var sway=randomRange(-80, 80);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: h + sh + 40,
x: sway + self._windOffset(dur),
rotation: randomRange(-180, 180),
duration: dur,
ease: 'sine.inOut',
onComplete: function(){
gsap.set(el, { x: 0, y: 0, left: randomRange(0, w) + 'px', rotation: 0 });
}});
})(i);
}}
_initBalloons(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(20, 35) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz * 1.2 + 'px',
backgroundColor: color,
borderRadius: '50% 50% 50% 50% / 40% 40% 60% 60%',
left: randomRange(0, w) + 'px',
top: h + sz + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
var str=createEl('div', {
position: 'absolute',
width: '1px',
height: sz * 0.5 + 'px',
backgroundColor: color,
left: sz / 2 + 'px',
top: sz * 1.2 + 'px',
opacity: '0.5'
}, el);
var dur=randomRange(5, 10) / self.opts.speed;
var delay=randomRange(0, 5);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: -(h + sz * 3),
x: '+=' + (randomRange(-100, 100) + self._windOffset(dur)),
rotation: randomRange(-20, 20),
duration: dur,
ease: 'none',
onComplete: function(){
gsap.set(el, { x: 0, y: 0, left: randomRange(0, w) + 'px' });
}});
self._addTween(gsap.to(el, {
x: '+=20', yoyo: true, repeat: -1,
duration: randomRange(1, 2) / self.opts.speed,
ease: 'sine.inOut'
}));
})();
}}
_initChampagne(){
var self=this;
var spawnBubble=function(){
var w=self._w(), h=self._h();
var sz=randomRange(3, 8) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: randomFrom(['#ffd700', '#ffe44d', '#fff8dc', '#ffc107']),
borderRadius: '50%',
left: w / 2 + randomRange(-80, 80) * self.opts.size + 'px',
top: h + 'px',
opacity: String(self.opts.opacity)
}, self.container);
if(self.opts.glow){
el.style.boxShadow='0 0 ' + (6 * self.opts.glowIntensity) + 'px ' + (3 * self.opts.glowIntensity) + 'px #ffd700';
}
var dur=randomRange(1.5, 3.5) / self.opts.speed;
self._addTween(gsap.to(el, {
y: -(h * randomRange(0.5, 1.2)),
x: randomRange(-150, 150) + self._windOffset(dur),
opacity: 0,
scale: randomRange(0.3, 0.8),
duration: dur,
ease: 'power1.out',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
};
for (var i=0; i < Math.floor(this.opts.count * 0.5); i++) spawnBubble();
this._addInterval(setInterval(function(){
if(!self._paused){
for (var j=0; j < 5; j++) spawnBubble();
}}, 200 / this.opts.speed));
}
_initGlitter(){
var self=this;
var w=this._w(), h=this._h();
var spawnGlitter=function(){
var sz=randomRange(2, 5) * self.opts.size;
var color=randomFrom(['#ffd700', '#c0c0c0', '#ffe44d', '#e8e8e8', '#fff8dc']);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: -sz + 'px',
opacity: '0'
}, self.container);
self._applyGlow(el, color);
var dur=randomRange(2, 5) / self.opts.speed;
var tl=gsap.timeline();
self._addTimeline(tl);
tl.to(el, {
y: h + sz,
x: randomRange(-50, 50) + self._windOffset(dur),
duration: dur,
ease: 'none'
});
tl.to(el, {
opacity: self.opts.opacity,
duration: 0.15,
yoyo: true,
repeat: Math.floor(dur / 0.3),
ease: 'power2.inOut'
}, 0);
tl.to(el, {
scale: randomRange(0.5, 1.5),
duration: 0.3,
yoyo: true,
repeat: -1,
ease: 'sine.inOut'
}, 0);
tl.eventCallback('onComplete', function(){
if(el.parentNode) el.parentNode.removeChild(el);
});
};
for (var i=0; i < this.opts.count; i++){
setTimeout(function(){ spawnGlitter(); }, randomRange(0, 2000));
}
this._addInterval(setInterval(function(){
if(!self._paused) spawnGlitter();
}, 100 / this.opts.speed));
}
_initStarburst(){
var self=this;
var burst=function(){
var w=self._w(), h=self._h();
for (var i=0; i < self.opts.count; i++){
var sz=randomRange(12, 24) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
left: w / 2 + 'px',
top: h / 2 + 'px',
fontSize: sz + 'px',
lineHeight: '1',
color: color,
opacity: '0',
pointerEvents: 'none'
}, self.container);
el.textContent='★';
self._applyTextGlow(el, color);
var angle=randomRange(0, Math.PI * 2);
var r=randomRange(80, Math.max(w, h) * 0.5);
var dur=randomRange(1, 2.5) / self.opts.speed;
var tl=gsap.timeline();
self._addTimeline(tl);
tl.fromTo(el, { opacity: 0, scale: 0 }, {
opacity: self.opts.opacity,
scale: 1,
x: Math.cos(angle) * r + self._windOffset(dur),
y: Math.sin(angle) * r,
rotation: randomRange(-360, 360),
duration: dur,
ease: 'power2.out'
});
tl.to(el, {
opacity: 0, scale: 0.3,
duration: dur * 0.4,
ease: 'power2.in',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }});
}};
burst();
this._addInterval(setInterval(burst, this.opts.burstInterval));
}
_initEmoji(){
var self=this;
var w=this._w(), h=this._h();
var spawnEmoji=function(){
var sz=randomRange(16, 32) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
fontSize: sz + 'px',
lineHeight: '1',
left: randomRange(0, w) + 'px',
top: -sz * 2 + 'px',
opacity: String(self.opts.opacity),
pointerEvents: 'none'
}, self.container);
el.textContent=randomFrom(EMOJIS);
var dur=randomRange(3, 6) / self.opts.speed;
self._addTween(gsap.to(el, {
y: h + sz * 2,
x: randomRange(-60, 60) + self._windOffset(dur),
rotation: randomRange(-180, 180),
duration: dur,
ease: 'none',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
};
for (var i=0; i < this.opts.count; i++){
setTimeout(function(){ spawnEmoji(); }, randomRange(0, 3000));
}
this._addInterval(setInterval(function(){
if(!self._paused) spawnEmoji();
}, 300 / this.opts.speed));
}
_initSnowfall(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(3, 8) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: '#ffffff',
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: randomRange(-sz, -sz * 5) + 'px',
opacity: String(randomRange(0.4, self.opts.opacity))
}, self.container);
self._applyGlow(el, '#ffffff');
var dur=randomRange(4, 8) / self.opts.speed;
var delay=randomRange(0, 5);
var swayX=randomRange(-60, 60);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: h + sz * 2,
x: swayX + self._windOffset(dur),
duration: dur,
ease: 'none',
onComplete: function(){
gsap.set(el, {
x: 0, y: 0,
left: randomRange(0, w) + 'px',
top: randomRange(-sz, -sz * 3) + 'px'
});
}});
self._addTween(gsap.to(el, {
x: '+=' + randomRange(-30, 30),
duration: randomRange(1.5, 3) / self.opts.speed,
yoyo: true, repeat: -1, ease: 'sine.inOut'
}));
})();
}}
_initFireflies(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomFrom(['#ffff00', '#ffee58', '#fff176', '#ffe082']);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: randomRange(0, h) + 'px',
opacity: '0'
}, self.container);
el.style.boxShadow='0 0 ' + (10 * self.opts.glowIntensity) + 'px ' + (5 * self.opts.glowIntensity) + 'px ' + color;
var moveDur=randomRange(4, 8) / self.opts.speed;
self._addTween(gsap.to(el, {
x: '+=' + randomRange(-120, 120),
y: '+=' + randomRange(-120, 120),
duration: moveDur,
yoyo: true, repeat: -1,
ease: 'sine.inOut'
}));
self._addTween(gsap.to(el, {
opacity: self.opts.opacity,
duration: randomRange(0.8, 2) / self.opts.speed,
yoyo: true, repeat: -1,
ease: 'sine.inOut',
delay: randomRange(0, 3)
}));
})();
}}
_initCherryBlossoms(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(8, 16) * self.opts.size;
var pink=randomFrom(['#ffb7c5', '#ff69b4', '#ffc0cb', '#f8bbd0', '#f48fb1']);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz * 0.6 + 'px',
backgroundColor: pink,
borderRadius: '50% 0 50% 0',
left: randomRange(0, w) + 'px',
top: -sz * 2 + 'px',
opacity: String(self.opts.opacity),
transformOrigin: 'center center'
}, self.container);
self._applyGlow(el, pink);
var dur=randomRange(4, 8) / self.opts.speed;
var delay=randomRange(0, 6);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: h + sz * 2,
x: randomRange(-100, 100) + self._windOffset(dur),
rotation: randomRange(-360, 360),
duration: dur,
ease: 'none',
onComplete: function(){
gsap.set(el, { x: 0, y: 0, left: randomRange(0, w) + 'px', rotation: 0 });
}});
self._addTween(gsap.to(el, {
x: '+=' + randomRange(-40, 40),
rotateY: 180,
duration: randomRange(1, 3) / self.opts.speed,
yoyo: true, repeat: -1, ease: 'sine.inOut'
}));
})();
}}
_initRain(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var len=randomRange(15, 30) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: '1px',
height: len + 'px',
backgroundColor: 'rgba(174,194,224,' + self.opts.opacity + ')',
left: randomRange(0, w) + 'px',
top: -len + 'px'
}, self.container);
var dur=randomRange(0.3, 0.8) / self.opts.speed;
var delay=randomRange(0, 2);
var windX=self.opts.wind * self.opts.windStrength * 10;
el.style.transform='rotate(' + (windX * 2) + 'deg)';
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: h + len,
x: windX * dur * 20,
duration: dur,
ease: 'none',
onComplete: function(){
gsap.set(el, { x: 0, y: 0, left: randomRange(0, w) + 'px' });
}});
})();
}
if(this.opts.glow){
var flash=createEl('div', {
position: 'absolute',
top: '0', left: '0', right: '0', bottom: '0',
backgroundColor: 'rgba(255,255,255,0)',
pointerEvents: 'none',
zIndex: '10'
}, this.container);
this._addInterval(setInterval(function(){
if(self._paused) return;
if(Math.random() > 0.7){
gsap.to(flash, { backgroundColor: 'rgba(255,255,255,0.3)', duration: 0.05,
onComplete: function(){
gsap.to(flash, { backgroundColor: 'rgba(255,255,255,0)', duration: 0.3 });
}});
}}, 3000));
}}
_initLeaves(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(10, 20) * self.opts.size;
var color=randomFrom(AUTUMN_COLORS);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz * 0.6 + 'px',
backgroundColor: color,
borderRadius: '0 50%',
left: randomRange(0, w) + 'px',
top: -sz * 2 + 'px',
opacity: String(self.opts.opacity),
transformOrigin: 'center center'
}, self.container);
self._applyGlow(el, color);
var dur=randomRange(4, 9) / self.opts.speed;
var delay=randomRange(0, 5);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: h + sz * 2,
x: randomRange(-120, 120) + self._windOffset(dur),
rotation: randomRange(-540, 540),
duration: dur,
ease: 'none',
onComplete: function(){
gsap.set(el, { x: 0, y: 0, left: randomRange(0, w) + 'px', rotation: 0 });
}});
self._addTween(gsap.to(el, {
scaleX: -1,
duration: randomRange(0.5, 1.5) / self.opts.speed,
yoyo: true, repeat: -1, ease: 'sine.inOut'
}));
})();
}}
_initBubbles(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(8, 25) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
border: '1px solid rgba(255,255,255,' + self.opts.opacity * 0.6 + ')',
backgroundColor: 'rgba(255,255,255,' + self.opts.opacity * 0.1 + ')',
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: h + sz + 'px'
}, self.container);
if(self.opts.glow){
el.style.boxShadow='0 0 ' + (8 * self.opts.glowIntensity) + 'px rgba(255,255,255,0.3)';
}
var dur=randomRange(4, 8) / self.opts.speed;
var delay=randomRange(0, 5);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
tl.to(el, {
y: -(h + sz * 3),
x: randomRange(-60, 60) + self._windOffset(dur),
duration: dur,
ease: 'none',
onComplete: function(){
gsap.set(el, { x: 0, y: 0, left: randomRange(0, w) + 'px', top: h + sz + 'px' });
}});
self._addTween(gsap.to(el, {
x: '+=' + randomRange(-20, 20),
duration: randomRange(1, 2.5) / self.opts.speed,
yoyo: true, repeat: -1, ease: 'sine.inOut'
}));
})();
}}
_initGalaxy(){
var self=this;
var w=this._w(), h=this._h();
var cx=w / 2, cy=h / 2;
var arms=3;
var galaxyContainer=createEl('div', {
position: 'absolute',
width: '100%', height: '100%',
top: '0', left: '0'
}, this.container);
for (var i=0; i < this.opts.count; i++){
(function(idx){
var arm=idx % arms;
var armAngle=(arm / arms) * Math.PI * 2;
var t=(idx / self.opts.count);
var maxR=Math.min(w, h) * 0.4;
var r=t * maxR;
var spiralAngle=armAngle + t * Math.PI * 3;
var jitter=randomRange(-15, 15);
var sz=randomRange(2, 5) * self.opts.size;
var color=lerpColor(self.opts.color1, self.opts.color2, t);
var x=cx + Math.cos(spiralAngle) * r + jitter;
var y=cy + Math.sin(spiralAngle) * r + jitter;
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: x + 'px',
top: y + 'px',
opacity: String(self.opts.opacity * randomRange(0.5, 1))
}, galaxyContainer);
self._applyGlow(el, color);
})(i);
}
var dur=30 / self.opts.speed;
self._addTween(gsap.to(galaxyContainer, {
rotation: 360,
duration: dur,
repeat: -1,
ease: 'none',
transformOrigin: '50% 50%'
}));
}
_initStarfield(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(1, 4) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: '#ffffff',
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: randomRange(0, h) + 'px',
opacity: String(randomRange(0.2, self.opts.opacity))
}, self.container);
self._applyGlow(el, '#ffffff');
self._addTween(gsap.to(el, {
opacity: randomRange(0.1, 0.3),
duration: randomRange(1, 3) / self.opts.speed,
yoyo: true, repeat: -1,
ease: 'sine.inOut',
delay: randomRange(0, 4)
}));
})();
}
this._addInterval(setInterval(function(){
if(self._paused) return;
var startX=randomRange(0, w * 0.5);
var startY=randomRange(0, h * 0.3);
var trail=createEl('div', {
position: 'absolute',
width: randomRange(40, 80) * self.opts.size + 'px',
height: '2px',
background: 'linear-gradient(to right, rgba(255,255,255,0), #ffffff)',
left: startX + 'px',
top: startY + 'px',
opacity: '0',
transformOrigin: 'right center',
transform: 'rotate(30deg)'
}, self.container);
var dur=randomRange(0.5, 1) / self.opts.speed;
var tl=gsap.timeline();
self._addTimeline(tl);
tl.to(trail, { opacity: self.opts.opacity, duration: 0.1 });
tl.to(trail, {
x: w * 0.6, y: h * 0.6, opacity: 0,
duration: dur, ease: 'power1.in',
onComplete: function(){ if(trail.parentNode) trail.parentNode.removeChild(trail); }});
}, 4000 / this.opts.speed));
}
_initNebula(){
var self=this;
var w=this._w(), h=this._h();
var blobCount=Math.min(6, Math.ceil(this.opts.count * 0.15));
for (var i=0; i < blobCount; i++){
(function(){
var sz=randomRange(100, 250) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
filter: 'blur(' + randomRange(40, 80) + 'px)',
left: randomRange(-sz * 0.3, w - sz * 0.5) + 'px',
top: randomRange(-sz * 0.3, h - sz * 0.5) + 'px',
opacity: String(self.opts.opacity * 0.3)
}, self.container);
var dur=randomRange(8, 15) / self.opts.speed;
self._addTween(gsap.to(el, {
x: randomRange(-50, 50),
y: randomRange(-50, 50),
scale: randomRange(0.8, 1.3),
duration: dur,
yoyo: true, repeat: -1,
ease: 'sine.inOut'
}));
})();
}
for (var j=0; j < this.opts.count; j++){
(function(){
var sz=randomRange(1, 3) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: '#ffffff',
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: randomRange(0, h) + 'px',
opacity: String(randomRange(0.3, self.opts.opacity))
}, self.container);
self._addTween(gsap.to(el, {
opacity: randomRange(0.1, 0.4),
duration: randomRange(1, 4) / self.opts.speed,
yoyo: true, repeat: -1, ease: 'sine.inOut',
delay: randomRange(0, 3)
}));
})();
}}
_initComets(){
var self=this;
var spawnComet=function(){
var w=self._w(), h=self._h();
var sz=randomRange(4, 8) * self.opts.size;
var tailLen=randomRange(60, 120) * self.opts.size;
var color=randomColorFromArray(self.colors);
var startY=randomRange(h * 0.1, h * 0.7);
var el=createEl('div', {
position: 'absolute',
width: tailLen + 'px',
height: sz + 'px',
background: 'linear-gradient(to right, transparent, ' + color + ')',
borderRadius: '0 50% 50% 0',
left: -tailLen + 'px',
top: startY + 'px',
opacity: String(self.opts.opacity)
}, self.container);
if(self.opts.glow){
el.style.boxShadow='0 0 ' + (15 * self.opts.glowIntensity) + 'px ' + color;
}
var dur=randomRange(1, 2.5) / self.opts.speed;
self._addTween(gsap.to(el, {
x: w + tailLen * 2,
y: randomRange(-30, 80),
duration: dur,
ease: 'power1.in',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
};
spawnComet();
this._addInterval(setInterval(function(){
if(!self._paused) spawnComet();
}, this.opts.burstInterval));
}
_initMatrix(){
var self=this;
var w=this._w(), h=this._h();
var colWidth=20 * this.opts.size;
var cols=Math.floor(w / colWidth);
var colCount=Math.min(cols, this.opts.count);
for (var i=0; i < colCount; i++){
(function(colIdx){
var x=colIdx * colWidth + colWidth / 2;
var charCount=Math.floor(h / (14 * self.opts.size)) + 5;
var delay=randomRange(0, 3);
var spawnColumn=function(){
var yPos=0;
for (var c=0; c < charCount; c++){
(function(charIdx){
var sz=randomRange(10, 14) * self.opts.size;
var el=createEl('div', {
position: 'absolute',
left: x + 'px',
top: -sz + 'px',
fontSize: sz + 'px',
fontFamily: 'monospace',
color: charIdx===0 ? '#ffffff':'#00ff00',
opacity: '0',
pointerEvents: 'none'
}, self.container);
el.textContent=randomFrom(MATRIX_CHARS.split(''));
var charDelay=delay + charIdx * 0.05;
var dur=randomRange(0.05, 0.1) / self.opts.speed;
var tl=gsap.timeline({ delay: charDelay });
self._addTimeline(tl);
tl.set(el, { y: charIdx * sz * 1.2 });
tl.to(el, {
opacity: self.opts.opacity * (1 - charIdx / charCount * 0.8),
duration: dur
});
tl.to(el, {
opacity: 0,
duration: randomRange(0.5, 1.5) / self.opts.speed,
delay: randomRange(0.5, 2),
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }});
self._addInterval(setInterval(function(){
if(el.parentNode) el.textContent=randomFrom(MATRIX_CHARS.split(''));
}, randomRange(100, 500)));
})(c);
}};
spawnColumn();
self._addInterval(setInterval(function(){
if(!self._paused) spawnColumn();
}, randomRange(3000, 6000) / self.opts.speed));
})(i);
}}
_initNetwork(){
var self=this;
var w=this._w(), h=this._h();
var svg=createSVG(this.container, w, h);
var nodes=[];
var lines=[];
for (var i=0; i < this.opts.count; i++){
(function(idx){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: randomRange(0, h) + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
var node={ el: el, vx: randomRange(-0.5, 0.5), vy: randomRange(-0.5, 0.5), color: color };
nodes.push(node);
var dur=randomRange(6, 12) / self.opts.speed;
self._addTween(gsap.to(el, {
x: '+=' + randomRange(-100, 100),
y: '+=' + randomRange(-100, 100),
duration: dur,
yoyo: true, repeat: -1,
ease: 'sine.inOut'
}));
})(i);
}
var maxLines=Math.min(this.opts.count * 3, 200);
for (var l=0; l < maxLines; l++){
var line=createSVGLine(svg);
line.setAttribute('stroke', self.opts.color1);
line.setAttribute('stroke-width', '1');
line.setAttribute('opacity', '0');
lines.push(line);
}
var updateConnections=function(){
if(self._destroyed) return;
var lineIdx=0;
var cDist=self.opts.connectionDistance;
for (var a=0; a < nodes.length; a++){
var ra=nodes[a].el.getBoundingClientRect();
var cr=self.container.getBoundingClientRect();
var ax=ra.left - cr.left + ra.width / 2;
var ay=ra.top - cr.top + ra.height / 2;
for (var b=a + 1; b < nodes.length; b++){
var rb=nodes[b].el.getBoundingClientRect();
var bx=rb.left - cr.left + rb.width / 2;
var by=rb.top - cr.top + rb.height / 2;
var d=dist(ax, ay, bx, by);
if(d < cDist&&lineIdx < lines.length){
var opacity=(1 - d / cDist) * self.opts.opacity;
lines[lineIdx].setAttribute('x1', ax);
lines[lineIdx].setAttribute('y1', ay);
lines[lineIdx].setAttribute('x2', bx);
lines[lineIdx].setAttribute('y2', by);
lines[lineIdx].setAttribute('opacity', opacity);
lineIdx++;
}}
}
for (var k=lineIdx; k < lines.length; k++){
lines[k].setAttribute('opacity', '0');
}
self._addRaf(requestAnimationFrame(updateConnections));
};
this._addRaf(requestAnimationFrame(updateConnections));
}
_initDna(){
var self=this;
var w=this._w(), h=this._h();
var cx=w / 2;
var pairs=this.opts.count;
var vertSpacing=h / (pairs + 1);
var radiusX=Math.min(w * 0.15, 80) * this.opts.size;
var helixContainer=createEl('div', {
position: 'absolute',
width: '100%', height: '100%',
top: '0', left: '0'
}, this.container);
var svg=createSVG(helixContainer, w, h);
var allNodes=[];
for (var i=0; i < pairs; i++){
(function(idx){
var yPos=vertSpacing * (idx + 1);
var phase=(idx / pairs) * Math.PI * 4;
var sz=randomRange(5, 8) * self.opts.size;
var leftEl=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: self.opts.color1,
borderRadius: '50%',
left: cx + 'px',
top: yPos + 'px',
opacity: String(self.opts.opacity)
}, helixContainer);
self._applyGlow(leftEl, self.opts.color1);
var rightEl=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: self.opts.color2,
borderRadius: '50%',
left: cx + 'px',
top: yPos + 'px',
opacity: String(self.opts.opacity)
}, helixContainer);
self._applyGlow(rightEl, self.opts.color2);
var line=createSVGLine(svg);
line.setAttribute('stroke', 'rgba(255,255,255,0.3)');
line.setAttribute('stroke-width', '1');
allNodes.push({ left: leftEl, right: rightEl, line: line, y: yPos, phase: phase });
})(i);
}
var time={ value: 0 };
self._addTween(gsap.to(time, {
value: Math.PI * 2,
duration: 4 / self.opts.speed,
repeat: -1,
ease: 'none',
onUpdate: function(){
for (var j=0; j < allNodes.length; j++){
var n=allNodes[j];
var angle=n.phase + time.value;
var lx=cx + Math.cos(angle) * radiusX;
var rx=cx + Math.cos(angle + Math.PI) * radiusX;
var lz=Math.sin(angle);
var rz=Math.sin(angle + Math.PI);
gsap.set(n.left, { left: lx + 'px', scale: 0.6 + lz * 0.4, zIndex: lz > 0 ? 2:0 });
gsap.set(n.right, { left: rx + 'px', scale: 0.6 + rz * 0.4, zIndex: rz > 0 ? 2:0 });
n.line.setAttribute('x1', lx);
n.line.setAttribute('y1', n.y);
n.line.setAttribute('x2', rx);
n.line.setAttribute('y2', n.y);
n.line.setAttribute('opacity', 0.3 * self.opts.opacity);
}}
}));
}
_initWave(){
var self=this;
var w=this._w(), h=this._h();
var cols=Math.ceil(Math.sqrt(this.opts.count * (w / h)));
var rows=Math.ceil(this.opts.count / cols);
var spacingX=w / (cols + 1);
var spacingY=h / (rows + 1);
var dots=[];
for (var r=0; r < rows; r++){
for (var c=0; c < cols; c++){
(function(row, col){
var sz=randomRange(3, 5) * self.opts.size;
var x=spacingX * (col + 1);
var y=spacingY * (row + 1);
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: x + 'px',
top: y + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
dots.push({ el: el, baseX: x, baseY: y, col: col, row: row });
})(r, c);
}}
var time={ value: 0 };
self._addTween(gsap.to(time, {
value: Math.PI * 200,
duration: 200 / self.opts.speed,
repeat: -1,
ease: 'none',
onUpdate: function(){
for (var i=0; i < dots.length; i++){
var d=dots[i];
var offsetY=Math.sin(time.value + d.col * 0.5 + d.row * 0.3) * 20 * self.opts.size;
gsap.set(d.el, { y: offsetY });
}}
}));
}
_initMagnetic(){
var self=this;
var w=this._w(), h=this._h();
var cx=w / 2, cy=h / 2;
for (var i=0; i < this.opts.count; i++){
(function(idx){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: cx + 'px',
top: cy + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
var rx=randomRange(30, Math.min(w, h) * 0.4) * self.opts.size;
var ry=rx * randomRange(0.3, 0.9);
var phase=randomRange(0, Math.PI * 2);
var dur=randomRange(4, 10) / self.opts.speed;
var time={ value: phase };
self._addTween(gsap.to(time, {
value: phase + Math.PI * 2,
duration: dur,
repeat: -1,
ease: 'none',
onUpdate: function(){
var x=Math.cos(time.value) * rx;
var y=Math.sin(time.value) * ry;
gsap.set(el, { x: x, y: y });
}}));
})(i);
}}
_initAurora(){
var self=this;
var w=this._w(), h=this._h();
var ribbonCount=Math.min(5, Math.ceil(this.opts.count * 0.1));
for (var i=0; i < ribbonCount; i++){
(function(){
var ribbonH=randomRange(40, 80) * self.opts.size;
var color=randomColorFromArray(self.colors);
var yPos=randomRange(h * 0.1, h * 0.6);
var el=createEl('div', {
position: 'absolute',
width: w * 1.5 + 'px',
height: ribbonH + 'px',
background: 'linear-gradient(90deg, transparent 0%, ' + color + ' 30%, ' + self.opts.color2 + ' 70%, transparent 100%)',
filter: 'blur(' + randomRange(20, 40) + 'px)',
left: -w * 0.25 + 'px',
top: yPos + 'px',
opacity: String(self.opts.opacity * 0.4)
}, self.container);
var dur=randomRange(6, 12) / self.opts.speed;
self._addTween(gsap.to(el, {
x: randomRange(-100, 100),
scaleY: randomRange(0.5, 1.5),
opacity: self.opts.opacity * randomRange(0.2, 0.5),
duration: dur,
yoyo: true, repeat: -1,
ease: 'sine.inOut'
}));
})();
}
for (var j=0; j < this.opts.count; j++){
(function(){
var sz=randomRange(1, 3) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: randomRange(0, w) + 'px',
top: randomRange(h * 0.05, h * 0.7) + 'px',
opacity: String(randomRange(0.2, self.opts.opacity))
}, self.container);
self._applyGlow(el, color);
self._addTween(gsap.to(el, {
x: randomRange(-30, 30),
y: randomRange(-20, 20),
opacity: randomRange(0.1, self.opts.opacity * 0.6),
duration: randomRange(2, 5) / self.opts.speed,
yoyo: true, repeat: -1,
ease: 'sine.inOut',
delay: randomRange(0, 3)
}));
})();
}}
_initGeometric(){
var self=this;
var w=this._w(), h=this._h();
for (var i=0; i < this.opts.count; i++){
(function(){
var shape=randomFrom(GEOMETRIC_SHAPES);
var sz=randomRange(15, 40) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
border: '2px solid ' + color,
backgroundColor: 'transparent',
left: randomRange(0, w) + 'px',
top: randomRange(0, h) + 'px',
opacity: String(self.opts.opacity * 0.7)
}, self.container);
self._applyGlow(el, color);
if(shape==='circle'){
el.style.borderRadius='50%';
}else if(shape==='square'){
el.style.borderRadius='4px';
}else if(shape==='triangle'){
el.style.border='none';
el.style.width='0';
el.style.height='0';
el.style.borderLeft=sz / 2 + 'px solid transparent';
el.style.borderRight=sz / 2 + 'px solid transparent';
el.style.borderBottom=sz + 'px solid ' + color;
el.style.backgroundColor='transparent';
}else if(shape==='hexagon'){
el.style.borderRadius='25%';
el.style.transform='rotate(30deg)';
}
var dur=randomRange(5, 12) / self.opts.speed;
self._addTween(gsap.to(el, {
x: randomRange(-80, 80),
y: randomRange(-80, 80),
rotation: '+=' + randomRange(90, 360),
duration: dur,
yoyo: true, repeat: -1,
ease: 'sine.inOut'
}));
})();
}}
_initPulseRings(){
var self=this;
var w=this._w(), h=this._h();
var cx=w / 2, cy=h / 2;
var spawnRing=function(){
var sz=10 * self.opts.size;
var maxSz=Math.min(w, h) * 0.8;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
border: '2px solid ' + color,
borderRadius: '50%',
left: cx - sz / 2 + 'px',
top: cy - sz / 2 + 'px',
opacity: String(self.opts.opacity)
}, self.container);
if(self.opts.glow){
el.style.boxShadow='0 0 ' + (10 * self.opts.glowIntensity) + 'px ' + color + ', inset 0 0 ' + (5 * self.opts.glowIntensity) + 'px ' + color;
}
var dur=randomRange(2, 4) / self.opts.speed;
self._addTween(gsap.to(el, {
width: maxSz, height: maxSz,
left: cx - maxSz / 2, top: cy - maxSz / 2,
opacity: 0,
borderWidth: 0.5,
duration: dur,
ease: 'power1.out',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
};
spawnRing();
var interval=Math.max(300, this.opts.burstInterval / this.opts.count * 3);
this._addInterval(setInterval(function(){
if(!self._paused) spawnRing();
}, interval));
}
_initVortex(){
var self=this;
var w=this._w(), h=this._h();
var cx=w / 2, cy=h / 2;
for (var i=0; i < this.opts.count; i++){
(function(idx){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: cx + 'px',
top: cy + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
var angle=randomRange(0, Math.PI * 2);
var maxRadius=randomRange(Math.min(w, h) * 0.3, Math.min(w, h) * 0.5);
var dur=randomRange(3, 7) / self.opts.speed;
var delay=randomRange(0, 3);
var tl=gsap.timeline({ repeat: -1, delay: delay });
self._addTimeline(tl);
var proxy={ r: maxRadius, a: angle };
tl.to(proxy, {
r: 5,
a: angle + Math.PI * 6,
duration: dur,
ease: 'power1.in',
onUpdate: function(){
var x=Math.cos(proxy.a) * proxy.r;
var y=Math.sin(proxy.a) * proxy.r;
gsap.set(el, { x: x, y: y, scale: proxy.r / maxRadius });
},
onComplete: function(){
proxy.r=maxRadius;
proxy.a=randomRange(0, Math.PI * 2);
gsap.set(el, { scale: 1 });
}});
})(i);
}}
_initSparks(){
var self=this;
var w=this._w(), h=this._h();
var spawnSpark=function(){
var sz=randomRange(2, 5) * self.opts.size;
var color=randomFrom(['#ff4500', '#ff6600', '#ff8c00', '#ffa500', '#ffd700', '#ffff00']);
var startX=randomRange(w * 0.2, w * 0.8);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: startX + 'px',
top: h + 'px',
opacity: String(self.opts.opacity)
}, self.container);
if(self.opts.glow){
el.style.boxShadow='0 0 ' + (8 * self.opts.glowIntensity) + 'px ' + color;
}
var dur=randomRange(1, 3) / self.opts.speed;
self._addTween(gsap.to(el, {
y: -(h * randomRange(0.3, 0.9)),
x: randomRange(-80, 80) + self._windOffset(dur),
opacity: 0,
scale: 0.1,
duration: dur,
ease: 'power2.out',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
};
for (var i=0; i < this.opts.count; i++){
setTimeout(function(){ spawnSpark(); }, randomRange(0, 1000));
}
this._addInterval(setInterval(function(){
if(!self._paused){
for (var j=0; j < 3; j++) spawnSpark();
}}, 150 / this.opts.speed));
}
_initDust(){
var self=this;
var w=this._w(), h=this._h();
var beamCx=w * 0.5, beamCy=h * 0.5;
var beamW=w * 0.6, beamH=h * 0.8;
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(1, 3) * self.opts.size;
var startX=beamCx + randomRange(-beamW / 2, beamW / 2);
var startY=beamCy + randomRange(-beamH / 2, beamH / 2);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: 'rgba(255,255,255,0.8)',
borderRadius: '50%',
left: startX + 'px',
top: startY + 'px',
opacity: String(randomRange(0.1, self.opts.opacity * 0.5))
}, self.container);
if(self.opts.glow){
el.style.boxShadow='0 0 ' + (4 * self.opts.glowIntensity) + 'px rgba(255,255,255,0.3)';
}
var dur=randomRange(5, 15) / self.opts.speed;
self._addTween(gsap.to(el, {
x: randomRange(-40, 40) + self._windOffset(dur),
y: randomRange(-30, 30),
opacity: randomRange(0.05, self.opts.opacity * 0.4),
duration: dur,
yoyo: true, repeat: -1,
ease: 'sine.inOut',
delay: randomRange(0, 5)
}));
})();
}}
_initBlobs(){
var self=this;
var w=this._w(), h=this._h();
var count=Math.min(this.opts.count, 12);
for (var i=0; i < count; i++){
(function(){
var sz=randomRange(60, 150) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: randomRange(30, 50) + '% ' + randomRange(50, 70) + '% ' + randomRange(30, 60) + '% ' + randomRange(40, 70) + '%',
filter: 'blur(' + randomRange(20, 40) + 'px)',
left: randomRange(-sz * 0.3, w - sz * 0.5) + 'px',
top: randomRange(-sz * 0.3, h - sz * 0.5) + 'px',
opacity: String(self.opts.opacity * 0.4)
}, self.container);
var dur=randomRange(8, 18) / self.opts.speed;
self._addTween(gsap.to(el, {
borderRadius: function(){
return randomRange(30, 60) + '% ' + randomRange(40, 70) + '% ' + randomRange(30, 60) + '% ' + randomRange(40, 70) + '%';
},
x: randomRange(-60, 60),
y: randomRange(-60, 60),
scale: randomRange(0.7, 1.4),
duration: dur,
yoyo: true, repeat: -1,
ease: 'sine.inOut'
}));
})();
}}
_initMouseAttract(){
var self=this;
var w=this._w(), h=this._h();
var nodes=[];
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(3, 7) * self.opts.size;
var color=randomColorFromArray(self.colors);
var baseX=randomRange(0, w);
var baseY=randomRange(0, h);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: baseX + 'px',
top: baseY + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
nodes.push({ el: el, baseX: baseX, baseY: baseY, x: baseX, y: baseY });
})();
}
var update=function(){
if(self._destroyed) return;
for (var i=0; i < nodes.length; i++){
var n=nodes[i];
if(self._mouseInside){
var dx=self._mouseX - n.x;
var dy=self._mouseY - n.y;
var d=Math.sqrt(dx * dx + dy * dy);
if(d < self.opts.forceRadius){
var force=(1 - d / self.opts.forceRadius) * self.opts.forceStrength * 2;
n.x +=dx * force * 0.05;
n.y +=dy * force * 0.05;
}else{
n.x +=(n.baseX - n.x) * 0.02;
n.y +=(n.baseY - n.y) * 0.02;
}}else{
n.x +=(n.baseX - n.x) * 0.02;
n.y +=(n.baseY - n.y) * 0.02;
}
gsap.set(n.el, { left: n.x + 'px', top: n.y + 'px' });
}
self._addRaf(requestAnimationFrame(update));
};
this._addRaf(requestAnimationFrame(update));
}
_initMouseRepel(){
var self=this;
var w=this._w(), h=this._h();
var nodes=[];
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(3, 7) * self.opts.size;
var color=randomColorFromArray(self.colors);
var baseX=randomRange(0, w);
var baseY=randomRange(0, h);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: baseX + 'px',
top: baseY + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
nodes.push({ el: el, baseX: baseX, baseY: baseY, x: baseX, y: baseY });
})();
}
var update=function(){
if(self._destroyed) return;
for (var i=0; i < nodes.length; i++){
var n=nodes[i];
if(self._mouseInside){
var dx=n.x - self._mouseX;
var dy=n.y - self._mouseY;
var d=Math.sqrt(dx * dx + dy * dy);
if(d < self.opts.forceRadius&&d > 0){
var force=(1 - d / self.opts.forceRadius) * self.opts.forceStrength * 5;
n.x +=(dx / d) * force;
n.y +=(dy / d) * force;
}else{
n.x +=(n.baseX - n.x) * 0.03;
n.y +=(n.baseY - n.y) * 0.03;
}}else{
n.x +=(n.baseX - n.x) * 0.03;
n.y +=(n.baseY - n.y) * 0.03;
}
gsap.set(n.el, { left: n.x + 'px', top: n.y + 'px' });
}
self._addRaf(requestAnimationFrame(update));
};
this._addRaf(requestAnimationFrame(update));
}
_initMouseTrail(){
var self=this;
var lastX=-1, lastY=-1;
var spawnTrail=function(){
if(self._destroyed||!self._mouseInside) return;
if(self._mouseX===lastX&&self._mouseY===lastY) return;
lastX=self._mouseX;
lastY=self._mouseY;
var sz=randomRange(4, 10) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: self._mouseX - sz / 2 + 'px',
top: self._mouseY - sz / 2 + 'px',
opacity: String(self.opts.opacity),
pointerEvents: 'none'
}, self.container);
self._applyGlow(el, color);
self._addTween(gsap.to(el, {
scale: 0,
opacity: 0,
x: randomRange(-20, 20),
y: randomRange(-20, 20),
duration: randomRange(0.5, 1.2) / self.opts.speed,
ease: 'power2.out',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
};
this._addInterval(setInterval(spawnTrail, 30));
}
_initHoverBurst(){
var self=this;
var lastBurstX=-1, lastBurstY=-1;
var minDist=30;
var doBurst=function(){
if(self._destroyed||!self._mouseInside) return;
var dx=self._mouseX - lastBurstX;
var dy=self._mouseY - lastBurstY;
if(Math.sqrt(dx * dx + dy * dy) < minDist) return;
lastBurstX=self._mouseX;
lastBurstY=self._mouseY;
var bCount=Math.min(8, Math.ceil(self.opts.count * 0.2));
for (var i=0; i < bCount; i++){
var sz=randomRange(2, 5) * self.opts.size;
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: self._mouseX + 'px',
top: self._mouseY + 'px',
opacity: String(self.opts.opacity),
pointerEvents: 'none'
}, self.container);
self._applyGlow(el, color);
var angle=randomRange(0, Math.PI * 2);
var r=randomRange(20, 60) * self.opts.size;
self._addTween(gsap.to(el, {
x: Math.cos(angle) * r,
y: Math.sin(angle) * r,
opacity: 0,
scale: 0.2,
duration: randomRange(0.4, 0.8) / self.opts.speed,
ease: 'power2.out',
onComplete: function(){ if(el.parentNode) el.parentNode.removeChild(el); }}));
}};
this._addInterval(setInterval(doBurst, 50));
}
_initSwarm(){
var self=this;
var w=this._w(), h=this._h();
var chain=[];
for (var i=0; i < this.opts.count; i++){
(function(idx){
var sz=randomRange(4, 8) * self.opts.size * (1 - idx / self.opts.count * 0.5);
var color=lerpColor(self.opts.color1, self.opts.color2, idx / self.opts.count);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: w / 2 + 'px',
top: h / 2 + 'px',
opacity: String(self.opts.opacity * (1 - idx / self.opts.count * 0.4)),
pointerEvents: 'none'
}, self.container);
self._applyGlow(el, color);
chain.push({ el: el, x: w / 2, y: h / 2 });
})(i);
}
var update=function(){
if(self._destroyed) return;
for (var i=0; i < chain.length; i++){
var target;
if(i===0){
target=self._mouseInside
? { x: self._mouseX, y: self._mouseY }
: { x: w / 2, y: h / 2 };}else{
target=chain[i - 1];
}
var easing=0.15 - i * 0.002;
if(easing < 0.02) easing=0.02;
chain[i].x +=(target.x - chain[i].x) * easing;
chain[i].y +=(target.y - chain[i].y) * easing;
gsap.set(chain[i].el, { left: chain[i].x + 'px', top: chain[i].y + 'px' });
}
self._addRaf(requestAnimationFrame(update));
};
this._addRaf(requestAnimationFrame(update));
}
_initGravityWell(){
var self=this;
var w=this._w(), h=this._h();
var particles=[];
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomColorFromArray(self.colors);
var px=randomRange(0, w), py=randomRange(0, h);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: px + 'px',
top: py + 'px',
opacity: String(self.opts.opacity),
pointerEvents: 'none'
}, self.container);
self._applyGlow(el, color);
particles.push({
el: el, x: px, y: py,
vx: randomRange(-0.5, 0.5),
vy: randomRange(-0.5, 0.5)
});
})();
}
var update=function(){
if(self._destroyed) return;
for (var i=0; i < particles.length; i++){
var p=particles[i];
if(self._mouseInside){
var dx=self._mouseX - p.x;
var dy=self._mouseY - p.y;
var d=Math.sqrt(dx * dx + dy * dy);
if(d > 1){
var force=self.opts.forceStrength * 50 / (d * d + 100);
p.vx +=(dx / d) * force;
p.vy +=(dy / d) * force;
}}
p.vx *=0.98;
p.vy *=0.98;
p.x +=p.vx;
p.y +=p.vy;
if(p.x < 0){ p.x=0; p.vx *=-0.5; }
if(p.x > w){ p.x=w; p.vx *=-0.5; }
if(p.y < 0){ p.y=0; p.vy *=-0.5; }
if(p.y > h){ p.y=h; p.vy *=-0.5; }
gsap.set(p.el, { left: p.x + 'px', top: p.y + 'px' });
}
self._addRaf(requestAnimationFrame(update));
};
this._addRaf(requestAnimationFrame(update));
}
_initConnectionWeb(){
var self=this;
var w=this._w(), h=this._h();
var svg=createSVG(this.container, w, h);
var nodes=[];
var linePool=[];
var maxLines=Math.min(this.opts.count * 2, 150);
for (var i=0; i < this.opts.count; i++){
(function(){
var sz=randomRange(3, 6) * self.opts.size;
var color=randomColorFromArray(self.colors);
var px=randomRange(0, w), py=randomRange(0, h);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: px + 'px',
top: py + 'px',
opacity: String(self.opts.opacity),
pointerEvents: 'none'
}, self.container);
self._applyGlow(el, color);
nodes.push({ el: el, x: px, y: py });
self._addTween(gsap.to(el, {
x: '+=' + randomRange(-60, 60),
y: '+=' + randomRange(-60, 60),
duration: randomRange(5, 10) / self.opts.speed,
yoyo: true, repeat: -1, ease: 'sine.inOut'
}));
})();
}
for (var l=0; l < maxLines; l++){
var line=createSVGLine(svg);
line.setAttribute('stroke', self.opts.color1);
line.setAttribute('stroke-width', '1');
line.setAttribute('opacity', '0');
linePool.push(line);
}
var update=function(){
if(self._destroyed) return;
var lineIdx=0;
var cDist=self.opts.connectionDistance;
var cr=self.container.getBoundingClientRect();
for (var i=0; i < nodes.length; i++){
var rect=nodes[i].el.getBoundingClientRect();
nodes[i].x=rect.left - cr.left + rect.width / 2;
nodes[i].y=rect.top - cr.top + rect.height / 2;
}
if(self._mouseInside){
for (var j=0; j < nodes.length; j++){
var d=dist(nodes[j].x, nodes[j].y, self._mouseX, self._mouseY);
if(d < cDist&&lineIdx < linePool.length){
var op=(1 - d / cDist) * self.opts.opacity;
linePool[lineIdx].setAttribute('x1', nodes[j].x);
linePool[lineIdx].setAttribute('y1', nodes[j].y);
linePool[lineIdx].setAttribute('x2', self._mouseX);
linePool[lineIdx].setAttribute('y2', self._mouseY);
linePool[lineIdx].setAttribute('opacity', op);
linePool[lineIdx].setAttribute('stroke', self.opts.color2);
lineIdx++;
}}
}
for (var a=0; a < nodes.length; a++){
for (var b=a + 1; b < nodes.length; b++){
var dd=dist(nodes[a].x, nodes[a].y, nodes[b].x, nodes[b].y);
if(dd < cDist&&lineIdx < linePool.length){
var opa=(1 - dd / cDist) * self.opts.opacity * 0.5;
linePool[lineIdx].setAttribute('x1', nodes[a].x);
linePool[lineIdx].setAttribute('y1', nodes[a].y);
linePool[lineIdx].setAttribute('x2', nodes[b].x);
linePool[lineIdx].setAttribute('y2', nodes[b].y);
linePool[lineIdx].setAttribute('opacity', opa);
linePool[lineIdx].setAttribute('stroke', self.opts.color1);
lineIdx++;
}}
}
for (var k=lineIdx; k < linePool.length; k++){
linePool[k].setAttribute('opacity', '0');
}
self._addRaf(requestAnimationFrame(update));
};
this._addRaf(requestAnimationFrame(update));
}
_initRipple(){
var self=this;
var w=this._w(), h=this._h();
var cols=Math.ceil(Math.sqrt(this.opts.count * (w / h)));
var rows=Math.ceil(this.opts.count / cols);
var spacingX=w / (cols + 1);
var spacingY=h / (rows + 1);
var dots=[];
for (var r=0; r < rows; r++){
for (var c=0; c < cols; c++){
(function(row, col){
var sz=randomRange(3, 5) * self.opts.size;
var x=spacingX * (col + 1);
var y=spacingY * (row + 1);
var color=randomColorFromArray(self.colors);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: x + 'px',
top: y + 'px',
opacity: String(self.opts.opacity)
}, self.container);
self._applyGlow(el, color);
dots.push({ el: el, baseX: x, baseY: y });
})(r, c);
}}
var update=function(){
if(self._destroyed) return;
for (var i=0; i < dots.length; i++){
var d=dots[i];
if(self._mouseInside){
var dx=d.baseX - self._mouseX;
var dy=d.baseY - self._mouseY;
var distance=Math.sqrt(dx * dx + dy * dy);
if(distance < self.opts.forceRadius * 2){
var force=(1 - distance / (self.opts.forceRadius * 2)) * self.opts.forceStrength * 30;
var ax=distance > 0 ? (dx / distance) * force:0;
var ay=distance > 0 ? (dy / distance) * force:0;
gsap.to(d.el, { x: ax, y: ay, duration: 0.3, ease: 'power2.out' });
}else{
gsap.to(d.el, { x: 0, y: 0, duration: 0.6, ease: 'power2.out' });
}}else{
gsap.to(d.el, { x: 0, y: 0, duration: 0.6, ease: 'power2.out' });
}}
self._addRaf(requestAnimationFrame(update));
};
var throttledUpdate=function(){
if(self._destroyed) return;
update();
setTimeout(function(){
self._addRaf(requestAnimationFrame(throttledUpdate));
}, 50);
};
this._addRaf(requestAnimationFrame(throttledUpdate));
}
_initOrbitCursor(){
var self=this;
var w=this._w(), h=this._h();
var orbiters=[];
var ringCount=this.opts.count;
for (var i=0; i < ringCount; i++){
(function(idx){
var sz=randomRange(3, 7) * self.opts.size;
var color=lerpColor(self.opts.color1, self.opts.color2, idx / ringCount);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: color,
borderRadius: '50%',
left: w / 2 + 'px',
top: h / 2 + 'px',
opacity: String(self.opts.opacity),
pointerEvents: 'none'
}, self.container);
self._applyGlow(el, color);
var radius=randomRange(20, 80) * self.opts.size;
var speed=randomRange(1, 3) * self.opts.speed;
var phase=(idx / ringCount) * Math.PI * 2;
orbiters.push({ el: el, radius: radius, speed: speed, phase: phase, x: w / 2, y: h / 2 });
})(i);
}
var startTime=Date.now();
var update=function(){
if(self._destroyed) return;
var t=(Date.now() - startTime) / 1000;
var targetX=self._mouseInside ? self._mouseX:w / 2;
var targetY=self._mouseInside ? self._mouseY:h / 2;
for (var i=0; i < orbiters.length; i++){
var o=orbiters[i];
o.x +=(targetX - o.x) * 0.08;
o.y +=(targetY - o.y) * 0.08;
var angle=o.phase + t * o.speed;
var px=o.x + Math.cos(angle) * o.radius;
var py=o.y + Math.sin(angle) * o.radius;
gsap.set(o.el, { left: px + 'px', top: py + 'px' });
}
self._addRaf(requestAnimationFrame(update));
};
this._addRaf(requestAnimationFrame(update));
}
_initColorWave(){
var self=this;
var w=this._w(), h=this._h();
var cols=Math.ceil(Math.sqrt(this.opts.count * (w / h)));
var rows=Math.ceil(this.opts.count / cols);
var spacingX=w / (cols + 1);
var spacingY=h / (rows + 1);
var dots=[];
for (var r=0; r < rows; r++){
for (var c=0; c < cols; c++){
(function(row, col){
var sz=randomRange(4, 7) * self.opts.size;
var x=spacingX * (col + 1);
var y=spacingY * (row + 1);
var el=createEl('div', {
position: 'absolute',
width: sz + 'px',
height: sz + 'px',
backgroundColor: self.opts.color1,
borderRadius: '50%',
left: x + 'px',
top: y + 'px',
opacity: String(self.opts.opacity)
}, self.container);
dots.push({ el: el, x: x, y: y });
})(r, c);
}}
var update=function(){
if(self._destroyed) return;
for (var i=0; i < dots.length; i++){
var d=dots[i];
if(self._mouseInside){
var distance=dist(d.x, d.y, self._mouseX, self._mouseY);
var maxDist=self.opts.forceRadius * 3;
var t=clamp(1 - distance / maxDist, 0, 1);
var color=lerpColor(self.opts.color1, self.opts.color2, t);
var scale=1 + t * 0.5;
d.el.style.backgroundColor=color;
gsap.to(d.el, { scale: scale, duration: 0.3, ease: 'power2.out' });
if(self.opts.glow&&t > 0.3){
d.el.style.boxShadow='0 0 ' + (t * 10 * self.opts.glowIntensity) + 'px ' + color;
}else{
d.el.style.boxShadow='none';
}}else{
d.el.style.backgroundColor=self.opts.color1;
d.el.style.boxShadow='none';
gsap.to(d.el, { scale: 1, duration: 0.5, ease: 'power2.out' });
}}
self._addRaf(requestAnimationFrame(update));
};
var throttled=function(){
if(self._destroyed) return;
update();
setTimeout(function(){
self._addRaf(requestAnimationFrame(throttled));
}, 50);
};
this._addRaf(requestAnimationFrame(throttled));
}
destroy(){
this._destroyed=true;
for (var i=0; i < this._intervals.length; i++){
clearInterval(this._intervals[i]);
}
this._intervals=[];
for (var j=0; j < this._rafs.length; j++){
cancelAnimationFrame(this._rafs[j]);
}
this._rafs=[];
for (var k=0; k < this._tweens.length; k++){
if(this._tweens[k]&&this._tweens[k].kill) this._tweens[k].kill();
}
this._tweens=[];
for (var l=0; l < this._timelines.length; l++){
if(this._timelines[l]&&this._timelines[l].kill) this._timelines[l].kill();
}
this._timelines=[];
if(this._scrollTrigger){
this._scrollTrigger.kill();
this._scrollTrigger=null;
}
if(this._observer){
this._observer.disconnect();
this._observer=null;
}
for (var m=0; m < this._listeners.length; m++){
var entry=this._listeners[m];
entry[0].removeEventListener(entry[1], entry[2]);
}
this._listeners=[];
if(this.container&&this.container.parentNode){
gsap.killTweensOf(this.container.querySelectorAll('*'));
this.container.parentNode.removeChild(this.container);
}
this.container=null;
}}
function autoInit(){
var elements=document.querySelectorAll('[data-particle-type]');
for (var i=0; i < elements.length; i++){
if(!elements[i]._dnxteParticleEngine){
elements[i]._dnxteParticleEngine=new DnxteParticleEngine(elements[i]);
}}
}
if(document.readyState==='loading'){
document.addEventListener('DOMContentLoaded', autoInit);
}else{
autoInit();
}
global.DnxteParticleEngine=DnxteParticleEngine;
})(window);