@@ -124,17 +124,20 @@ class HeaderCanvas extends Base {
124124 initParticles ( width , height ) {
125125 let me = this ;
126126 me . particles = [ ] ;
127- const count = 80 ;
127+ const count = 60 ;
128128
129129 for ( let i = 0 ; i < count ; i ++ ) {
130+ let isNebula = Math . random ( ) > 0.8 ; // 20% are large nebula orbs
131+
130132 me . particles . push ( {
131- x : Math . random ( ) * width ,
132- y : Math . random ( ) * height ,
133- vx : ( Math . random ( ) * 0.5 ) + 0.1 , // Drift velocity
134- vy : ( Math . random ( ) - 0.5 ) * 0.2 ,
135- size : Math . random ( ) * 2 + 0.5 ,
136- alpha : Math . random ( ) * 0.3 + 0.1 , // Faint
137- baseAlpha : Math . random ( ) * 0.3 + 0.1
133+ isNebula : isNebula ,
134+ x : Math . random ( ) * width ,
135+ y : Math . random ( ) * height ,
136+ vx : isNebula ? ( Math . random ( ) * 0.2 + 0.05 ) : ( Math . random ( ) * 0.5 + 0.1 ) , // Nebulae move slower
137+ vy : ( Math . random ( ) - 0.5 ) * 0.2 ,
138+ size : isNebula ? ( Math . random ( ) * 30 + 20 ) : ( Math . random ( ) * 2 + 0.5 ) , // Large vs Small
139+ alpha : isNebula ? ( Math . random ( ) * 0.15 + 0.1 ) : ( Math . random ( ) * 0.3 + 0.1 ) , // BOOSTED ALPHA
140+ baseAlpha : isNebula ? ( Math . random ( ) * 0.15 + 0.1 ) : ( Math . random ( ) * 0.3 + 0.1 )
138141 } )
139142 }
140143 }
@@ -161,8 +164,8 @@ class HeaderCanvas extends Base {
161164
162165 me . time += 0.05 ;
163166
164- // Auto-reinit particles if size changes significantly or empty
165- if ( me . particles . length === 0 ) {
167+ // Auto-reinit particles if size changes significantly or empty OR count mismatch (config update)
168+ if ( me . particles . length !== 60 ) {
166169 me . initParticles ( width , height )
167170 }
168171
@@ -195,43 +198,57 @@ class HeaderCanvas extends Base {
195198 drawParticles ( ctx , width , height ) {
196199 let me = this ;
197200
198- ctx . fillStyle = HIGHLIGHT ;
199-
200201 me . particles . forEach ( p => {
201202 // Update Position
202203 p . x += p . vx ;
203204 p . y += p . vy ;
204205
205206 // Wrap around
206- if ( p . x > width ) p . x = - 10 ;
207- if ( p . x < - 10 ) p . x = width ;
208- if ( p . y > height ) p . y = - 10 ;
209- if ( p . y < - 10 ) p . y = height ;
207+ if ( p . x > width + p . size ) p . x = - p . size ;
208+ if ( p . x < - p . size ) p . x = width + p . size ;
209+ if ( p . y > height + p . size ) p . y = - p . size ;
210+ if ( p . y < - p . size ) p . y = height + p . size ;
210211
211- // Mouse Interaction (Repulsion)
212+ // Mouse Interaction (Repulsion) - Only for small dust? Or both?
213+ // Let's affect both but nebulae have high mass (less effect)
212214 let dx = p . x - me . mouse . x ,
213215 dy = p . y - me . mouse . y ,
214216 dist = Math . sqrt ( dx * dx + dy * dy ) ,
215- maxDist = 100 ;
217+ maxDist = p . isNebula ? 150 : 100 ;
216218
217219 if ( dist < maxDist && dist > 0 ) {
218220 let force = ( maxDist - dist ) / maxDist ;
219221 // Push away
220- p . x += ( dx / dist ) * force * 2 ;
221- p . y += ( dy / dist ) * force * 2 ;
222- // Brighten
223- p . alpha = Math . min ( p . baseAlpha + force * 0.5 , 0.8 ) ;
222+ let mass = p . isNebula ? 5 : 1 ;
223+ p . x += ( dx / dist ) * force * ( 2 / mass ) ;
224+ p . y += ( dy / dist ) * force * ( 2 / mass ) ;
225+ // Brighten slightly
226+ p . alpha = Math . min ( p . baseAlpha + force * ( p . isNebula ? 0.05 : 0.5 ) , 0.8 ) ;
224227 } else {
225228 // Return to base alpha
226229 if ( p . alpha > p . baseAlpha ) {
227- p . alpha -= 0.01
230+ p . alpha -= 0.005
228231 }
229232 }
230233
231234 ctx . globalAlpha = p . alpha ;
232235 ctx . beginPath ( ) ;
233- ctx . arc ( p . x , p . y , p . size , 0 , Math . PI * 2 ) ;
234- ctx . fill ( ) ;
236+
237+ if ( p . isNebula ) {
238+ // Soft gradient for nebula
239+ // Since this is expensive, maybe just low alpha circle is enough?
240+ // Gradient is better for "Cloud" look.
241+ let g = ctx . createRadialGradient ( p . x , p . y , 0 , p . x , p . y , p . size ) ;
242+ g . addColorStop ( 0 , HIGHLIGHT ) ;
243+ g . addColorStop ( 1 , 'rgba(255,255,255,0)' ) ;
244+ ctx . fillStyle = g ;
245+ ctx . arc ( p . x , p . y , p . size , 0 , Math . PI * 2 ) ;
246+ ctx . fill ( ) ;
247+ } else {
248+ ctx . fillStyle = HIGHLIGHT ;
249+ ctx . arc ( p . x , p . y , p . size , 0 , Math . PI * 2 ) ;
250+ ctx . fill ( ) ;
251+ }
235252 } ) ;
236253
237254 ctx . globalAlpha = 1 ;
0 commit comments