@@ -156,9 +156,11 @@ export const gradientWave = (canvas, ctx) => {
156156 * @param {CanvasRenderingContext2D } ctx - The canvas 2D rendering context
157157 * @returns {Function } Animation loop function
158158 */
159- export const particleNetwork = ( canvas , ctx ) => {
159+ export const particleNetwork = ( canvas , ctx , options = { } ) => {
160+ const { themeManager, interactionHandler, performanceMonitor, adaptivePerformance } = options ;
161+
160162 const particles = [ ] ;
161- const particleCount = 150 ;
163+ const particleCount = adaptivePerformance ? Math . min ( 150 , Math . max ( 50 , navigator . hardwareConcurrency * 20 ) ) : 150 ;
162164 const maxDistance = 120 ;
163165
164166 for ( let i = 0 ; i < particleCount ; i ++ ) {
@@ -168,27 +170,60 @@ export const particleNetwork = (canvas, ctx) => {
168170 radius : Math . random ( ) * 3 + 1 ,
169171 vx : Math . random ( ) * 1.5 - 0.75 ,
170172 vy : Math . random ( ) * 1.5 - 0.75 ,
171- color : `hsl(${ Math . random ( ) * 360 } , 70%, 70%)`
173+ originalVx : Math . random ( ) * 1.5 - 0.75 ,
174+ originalVy : Math . random ( ) * 1.5 - 0.75 ,
175+ color : themeManager ? themeManager . getCurrentColors ( ) [ 0 ] : `hsl(${ Math . random ( ) * 360 } , 70%, 70%)`
172176 } ) ;
173177 }
174178
175179 return ( ) => {
176- ctx . fillStyle = 'rgba(15, 23, 42, 0.1)' ;
180+ // Use theme-aware background
181+ const bgColor = themeManager ? themeManager . getBackgroundColor ( ) : 'rgba(15, 23, 42, 0.1)' ;
182+ ctx . fillStyle = bgColor ;
177183 ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
178184
185+ // Apply interactions if available
186+ if ( interactionHandler ) {
187+ const interactionPoints = interactionHandler . getInteractionPoints ( ) ;
188+
189+ particles . forEach ( particle => {
190+ // Reset to original velocity
191+ particle . vx = particle . originalVx ;
192+ particle . vy = particle . originalVy ;
193+
194+ // Apply interaction forces
195+ interactionPoints . forEach ( point => {
196+ const force = interactionHandler . calculateInteractionForce ( particle , point ) ;
197+ particle . vx += force . fx * 2 ; // Amplify force for visibility
198+ particle . vy += force . fy * 2 ;
199+ } ) ;
200+ } ) ;
201+ }
202+
179203 particles . forEach ( particle => {
180204 particle . x += particle . vx ;
181205 particle . y += particle . vy ;
182206
183- if ( particle . x < 0 || particle . x > canvas . width ) particle . vx *= - 1 ;
184- if ( particle . y < 0 || particle . y > canvas . height ) particle . vy *= - 1 ;
207+ // Bounce off walls with dampening
208+ if ( particle . x < 0 || particle . x > canvas . width ) {
209+ particle . vx *= - 0.8 ;
210+ particle . originalVx *= - 0.8 ;
211+ particle . x = Math . max ( 0 , Math . min ( canvas . width , particle . x ) ) ;
212+ }
213+ if ( particle . y < 0 || particle . y > canvas . height ) {
214+ particle . vy *= - 0.8 ;
215+ particle . originalVy *= - 0.8 ;
216+ particle . y = Math . max ( 0 , Math . min ( canvas . height , particle . y ) ) ;
217+ }
185218
219+ // Draw particle
186220 ctx . beginPath ( ) ;
187221 ctx . arc ( particle . x , particle . y , particle . radius , 0 , Math . PI * 2 ) ;
188222 ctx . fillStyle = particle . color ;
189223 ctx . fill ( ) ;
190224 } ) ;
191225
226+ // Draw connections between nearby particles
192227 for ( let i = 0 ; i < particles . length ; i ++ ) {
193228 for ( let j = i + 1 ; j < particles . length ; j ++ ) {
194229 const dx = particles [ i ] . x - particles [ j ] . x ;
@@ -199,7 +234,29 @@ export const particleNetwork = (canvas, ctx) => {
199234 ctx . beginPath ( ) ;
200235 ctx . moveTo ( particles [ i ] . x , particles [ i ] . y ) ;
201236 ctx . lineTo ( particles [ j ] . x , particles [ j ] . y ) ;
202- ctx . strokeStyle = `rgba(255, 255, 255, ${ 1 - distance / maxDistance } )` ;
237+
238+ const opacity = 1 - distance / maxDistance ;
239+
240+ // Get line color from theme or use default
241+ let lineColor = 'rgba(255, 255, 255, 1)' ;
242+ if ( themeManager ) {
243+ const themeColors = themeManager . getCurrentColors ( ) ;
244+ const colorIndex = themeColors . length > 1 ? 1 : 0 ;
245+ const hexColor = themeColors [ colorIndex ] ;
246+
247+ // Convert hex to rgba
248+ if ( hexColor . startsWith ( '#' ) ) {
249+ const rgb = themeManager . parseColor ( hexColor ) ;
250+ lineColor = `rgba(${ rgb . r } , ${ rgb . g } , ${ rgb . b } , ${ opacity } )` ;
251+ } else {
252+ // Handle already rgb/rgba colors
253+ lineColor = hexColor . includes ( 'rgba' ) ? hexColor : hexColor . replace ( 'rgb' , 'rgba' ) . replace ( ')' , `, ${ opacity } )` ) ;
254+ }
255+ } else {
256+ lineColor = `rgba(255, 255, 255, ${ opacity } )` ;
257+ }
258+
259+ ctx . strokeStyle = lineColor ;
203260 ctx . lineWidth = 0.5 ;
204261 ctx . stroke ( ) ;
205262 }
0 commit comments