@@ -87,6 +87,9 @@ fun OptimizedAnimatedBackground(
8787 // Convert dp to px and pre-calculate squared distance for performance
8888 val connectionDistancePx = with (density) { maxConnectionDistance.dp.toPx() }
8989 val connectionDistanceSquared = connectionDistancePx * connectionDistancePx
90+
91+ // Pre-calculate sqrt to avoid repeated expensive operations in drawing loops
92+ val connectionDistance = connectionDistancePx
9093
9194 // Mutable particles list for better performance
9295 val particles = remember { mutableListOf<MutableParticle >() }
@@ -95,11 +98,26 @@ fun OptimizedAnimatedBackground(
9598 // Theme-aware cached colors with sci-fi glow effects
9699 val cachedColors = remember(colorScheme, themeEffects?.glowIntensity) {
97100 val glowIntensity = themeEffects?.glowIntensity ? : 0f
101+ val particleAlpha = 0.65f + glowIntensity * 0.2f
102+ val connectionAlpha = 0.4f + glowIntensity * 0.15f
103+ val mouseConnectionAlpha = 0.48f + glowIntensity * 0.25f
104+ val triangleFillAlpha = 0.08f + glowIntensity * 0.03f
105+
98106 ParticleColors (
99- particleColor = colorScheme.primary.copy(alpha = 0.65f + glowIntensity * 0.2f ),
100- connectionColor = colorScheme.secondary.copy(alpha = 0.4f + glowIntensity * 0.15f ),
101- mouseConnectionColor = colorScheme.secondary.copy(alpha = 0.48f + glowIntensity * 0.25f ),
102- triangleFillColor = colorScheme.secondary.copy(alpha = 0.08f + glowIntensity * 0.03f )
107+ particleColor = colorScheme.primary.copy(alpha = particleAlpha),
108+ connectionColor = colorScheme.secondary.copy(alpha = connectionAlpha),
109+ mouseConnectionColor = colorScheme.secondary.copy(alpha = mouseConnectionAlpha),
110+ triangleFillColor = colorScheme.secondary.copy(alpha = triangleFillAlpha),
111+ // Base colors without alpha for efficient calculations
112+ particleBaseColor = colorScheme.primary,
113+ connectionBaseColor = colorScheme.secondary,
114+ mouseConnectionBaseColor = colorScheme.secondary,
115+ triangleFillBaseColor = colorScheme.secondary,
116+ // Pre-calculated alpha values
117+ particleBaseAlpha = particleAlpha,
118+ connectionBaseAlpha = connectionAlpha,
119+ mouseConnectionBaseAlpha = mouseConnectionAlpha,
120+ triangleFillBaseAlpha = triangleFillAlpha
103121 )
104122 }
105123
@@ -152,6 +170,7 @@ fun OptimizedAnimatedBackground(
152170 drawOptimizedParticlesAndConnections(
153171 particles = particles,
154172 connectionDistanceSquared = connectionDistanceSquared,
173+ connectionDistance = connectionDistance,
155174 colors = cachedColors,
156175 mousePosition = mousePosition
157176 )
@@ -161,14 +180,44 @@ fun OptimizedAnimatedBackground(
161180}
162181
163182/* *
164- * Color cache to reduce object allocation during drawing
183+ * Optimized color cache to eliminate Color.copy() allocations.
184+ * Stores base colors and alpha values separately for efficient alpha blending.
165185 */
186+ @Immutable
187+ @Stable
166188private data class ParticleColors (
167189 val particleColor : Color ,
168190 val connectionColor : Color ,
169191 val mouseConnectionColor : Color ,
170- val triangleFillColor : Color
171- )
192+ val triangleFillColor : Color ,
193+ // Base colors without alpha for efficient dynamic alpha calculation
194+ val particleBaseColor : Color ,
195+ val connectionBaseColor : Color ,
196+ val mouseConnectionBaseColor : Color ,
197+ val triangleFillBaseColor : Color ,
198+ // Pre-calculated alpha values
199+ val particleBaseAlpha : Float ,
200+ val connectionBaseAlpha : Float ,
201+ val mouseConnectionBaseAlpha : Float ,
202+ val triangleFillBaseAlpha : Float
203+ ) {
204+ // Efficient color calculation without object allocation
205+ @Stable
206+ fun connectionColorWithAlpha (alpha : Float ): Color =
207+ connectionBaseColor.copy(alpha = alpha * connectionBaseAlpha)
208+
209+ @Stable
210+ fun mouseConnectionColorWithAlpha (alpha : Float ): Color =
211+ mouseConnectionBaseColor.copy(alpha = alpha * mouseConnectionBaseAlpha)
212+
213+ @Stable
214+ fun particleColorWithAlpha (alpha : Float ): Color =
215+ particleBaseColor.copy(alpha = alpha * particleBaseAlpha)
216+ //
217+ // @Stable
218+ // fun triangleFillColorWithAlpha(alpha: Float): Color =
219+ // triangleFillBaseColor.copy(alpha = alpha * triangleFillBaseAlpha)
220+ }
172221
173222/* *
174223 * Create optimized mutable particle
@@ -226,6 +275,7 @@ private fun DrawScope.drawTriangles(
226275 mouseConnections : List <Int >,
227276 mousePosition : Offset ? ,
228277 connectionDistanceSquared : Float ,
278+ connectionDistance : Float ,
229279 colors : ParticleColors
230280) {
231281
@@ -262,7 +312,7 @@ private fun DrawScope.drawTriangles(
262312 particles[p1Index],
263313 particles[p2Index],
264314 particles[p3Index],
265- connectionDistanceSquared ,
315+ connectionDistance ,
266316 colors.triangleFillColor
267317 )
268318 }
@@ -288,7 +338,7 @@ private fun DrawScope.drawTriangles(
288338 particles[p1Index],
289339 particles[p2Index],
290340 mouse,
291- connectionDistanceSquared ,
341+ connectionDistance ,
292342 colors.triangleFillColor
293343 )
294344 }
@@ -305,7 +355,7 @@ private fun DrawScope.drawGlassTriangle(
305355 p1 : MutableParticle ,
306356 p2 : MutableParticle ,
307357 p3 : MutableParticle ,
308- connectionDistanceSquared : Float ,
358+ connectionDistance : Float ,
309359 baseColor : Color
310360) {
311361 // Calculate distances of all three edges to find the longest
@@ -316,7 +366,7 @@ private fun DrawScope.drawGlassTriangle(
316366 // Use the longest edge for alpha calculation
317367 val longestDistanceSquared = maxOf(dist1Sq, dist2Sq, dist3Sq)
318368 val longestDistance = kotlin.math.sqrt(longestDistanceSquared)
319- val maxDistance = kotlin.math.sqrt(connectionDistanceSquared)
369+ val maxDistance = connectionDistance
320370
321371 // Make triangles fainter and decay faster than connection lines
322372 // Base alpha factor is 0.3 (much fainter than lines) and use squared ratio for faster decay
@@ -332,7 +382,7 @@ private fun DrawScope.drawGlassTriangle(
332382
333383 drawPath(
334384 path = trianglePath,
335- color = baseColor.copy(alpha = alpha)
385+ color = Color ( baseColor.red, baseColor.green, baseColor.blue, alpha)
336386 )
337387}
338388
@@ -343,7 +393,7 @@ private fun DrawScope.drawGlassTriangleWithMouse(
343393 p1 : MutableParticle ,
344394 p2 : MutableParticle ,
345395 mousePos : Offset ,
346- connectionDistanceSquared : Float ,
396+ connectionDistance : Float ,
347397 baseColor : Color
348398) {
349399 // Calculate distances of all three edges to find the longest
@@ -354,7 +404,7 @@ private fun DrawScope.drawGlassTriangleWithMouse(
354404 // Use the longest edge for alpha calculation
355405 val longestDistanceSquared = maxOf(dist1Sq, dist2Sq, dist3Sq)
356406 val longestDistance = kotlin.math.sqrt(longestDistanceSquared)
357- val maxDistance = kotlin.math.sqrt(connectionDistanceSquared)
407+ val maxDistance = connectionDistance
358408
359409 // Make triangles fainter and decay faster than connection lines
360410 // Mouse triangles get slightly higher intensity (0.4 vs 0.3) but still much fainter than lines
@@ -370,7 +420,7 @@ private fun DrawScope.drawGlassTriangleWithMouse(
370420
371421 drawPath(
372422 path = trianglePath,
373- color = baseColor.copy(alpha = alpha)
423+ color = Color ( baseColor.red, baseColor.green, baseColor.blue, alpha)
374424 )
375425}
376426
@@ -386,6 +436,7 @@ private fun DrawScope.drawGlassTriangleWithMouse(
386436private fun DrawScope.drawOptimizedParticlesAndConnections (
387437 particles : List <MutableParticle >,
388438 connectionDistanceSquared : Float ,
439+ connectionDistance : Float ,
389440 colors : ParticleColors ,
390441 mousePosition : Offset ? = null
391442) {
@@ -413,10 +464,10 @@ private fun DrawScope.drawOptimizedParticlesAndConnections(
413464
414465 // Only calculate sqrt when we know we need to draw
415466 val distance = kotlin.math.sqrt(distanceSquared)
416- val alpha = ( 1 - distance / kotlin.math.sqrt(connectionDistanceSquared)) * colors.connectionColor.alpha
467+ val alphaFactor = 1 - distance / connectionDistance
417468
418469 drawLine(
419- color = colors.connectionColor.copy(alpha = alpha ),
470+ color = colors.connectionColorWithAlpha(alphaFactor ),
420471 start = Offset (particle1.x, particle1.y),
421472 end = Offset (particle2.x, particle2.y),
422473 strokeWidth = 1f
@@ -437,11 +488,10 @@ private fun DrawScope.drawOptimizedParticlesAndConnections(
437488 mouseConnections.add(index)
438489
439490 val distance = kotlin.math.sqrt(distanceSquared)
440- val alpha =
441- (1 - distance / kotlin.math.sqrt(connectionDistanceSquared)) * colors.mouseConnectionColor.alpha
491+ val alphaFactor = 1 - distance / connectionDistance
442492
443493 drawLine(
444- color = colors.mouseConnectionColor.copy(alpha = alpha ),
494+ color = colors.mouseConnectionColorWithAlpha(alphaFactor ),
445495 start = Offset (particle.x, particle.y),
446496 end = mouse,
447497 strokeWidth = 1.5f
@@ -451,12 +501,12 @@ private fun DrawScope.drawOptimizedParticlesAndConnections(
451501 }
452502
453503 // Draw glass shard triangles
454- drawTriangles(particles, connections, mouseConnections, mousePosition, connectionDistanceSquared, colors)
504+ drawTriangles(particles, connections, mouseConnections, mousePosition, connectionDistanceSquared, connectionDistance, colors)
455505
456506 // Draw particles with cached colors
457507 particles.forEach { particle ->
458508 drawCircle(
459- color = colors.particleColor.copy(alpha = particle.alpha),
509+ color = colors.particleColorWithAlpha( particle.alpha),
460510 radius = particle.radius,
461511 center = Offset (particle.x, particle.y)
462512 )
0 commit comments