perf: cache WaveGraphic paths per size (was rebuilding ~3k lineTo per draw frame) + measured motion pass
This commit is contained in:
parent
e5a64e1892
commit
bd4f6bb874
1 changed files with 39 additions and 30 deletions
|
|
@ -84,6 +84,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
|
|
@ -440,41 +441,49 @@ private fun WaveGraphic(modifier: Modifier = Modifier) {
|
|||
val gradientColors = listOf(LocalTokens.current.accentFill, GradientMid, GradientEnd)
|
||||
val accentGlow = LocalTokens.current.accentFill
|
||||
|
||||
Canvas(modifier = modifier) {
|
||||
// Build each wave path + its gradient ONCE per size/palette, not per draw
|
||||
// pass: this canvas sits on the hub, and rebuilding ~1k lineTo segments
|
||||
// per layer was the heavy frame behind the hub-transition jank (99th-p
|
||||
// ~200ms). 4px steps are indistinguishable at this frequency and cut
|
||||
// segment count by 4x.
|
||||
var canvasSize by remember { mutableStateOf(androidx.compose.ui.unit.IntSize.Zero) }
|
||||
val layers = remember(canvasSize, gradientColors) {
|
||||
val w = canvasSize.width.toFloat()
|
||||
val h = canvasSize.height.toFloat()
|
||||
if (w <= 0f || h <= 0f) emptyList()
|
||||
else (0..2).map { layer ->
|
||||
val amplitude = (30f - layer * 8f) * (w / 400f)
|
||||
val frequency = 0.008f + layer * 0.002f
|
||||
val phaseShift = layer * 0.5f
|
||||
val path = Path().apply {
|
||||
moveTo(0f, h / 2 + amplitude * kotlin.math.sin(phaseShift.toDouble()).toFloat())
|
||||
var x = 0f
|
||||
while (x <= w) {
|
||||
val y = h / 2 + amplitude * kotlin.math.sin(
|
||||
(x * frequency * Math.PI * 2).toDouble() + phaseShift
|
||||
).toFloat()
|
||||
lineTo(x, y)
|
||||
x += 4f
|
||||
}
|
||||
}
|
||||
val strokeBrush = Brush.horizontalGradient(
|
||||
colors = gradientColors.map { it.copy(alpha = 0.6f - layer * 0.15f) },
|
||||
startX = 0f,
|
||||
endX = w,
|
||||
)
|
||||
Triple(path, strokeBrush, (3f - layer * 0.5f) * (w / 400f))
|
||||
}
|
||||
}
|
||||
|
||||
Canvas(
|
||||
modifier = modifier.onSizeChanged { canvasSize = it },
|
||||
) {
|
||||
val width = size.width
|
||||
val height = size.height
|
||||
val centerY = height / 2
|
||||
|
||||
// Draw multiple wave layers
|
||||
for (layer in 0..2) {
|
||||
val path = Path()
|
||||
val amplitude = (30f - layer * 8f) * (width / 400f)
|
||||
val frequency = 0.008f + layer * 0.002f
|
||||
val phaseShift = layer * 0.5f
|
||||
|
||||
path.moveTo(0f, centerY)
|
||||
|
||||
for (x in 0..width.toInt()) {
|
||||
val xFloat = x.toFloat()
|
||||
val y = centerY + amplitude * kotlin.math.sin(
|
||||
(xFloat * frequency * Math.PI * 2).toDouble() + phaseShift
|
||||
).toFloat()
|
||||
if (x == 0) {
|
||||
path.moveTo(xFloat, y)
|
||||
} else {
|
||||
path.lineTo(xFloat, y)
|
||||
}
|
||||
}
|
||||
|
||||
drawPath(
|
||||
path = path,
|
||||
brush = Brush.horizontalGradient(
|
||||
colors = gradientColors.map { it.copy(alpha = 0.6f - layer * 0.15f) },
|
||||
startX = 0f,
|
||||
endX = width,
|
||||
),
|
||||
style = Stroke(width = (3f - layer * 0.5f) * (width / 400f)),
|
||||
)
|
||||
for ((path, strokeBrush, strokeWidth) in layers) {
|
||||
drawPath(path = path, brush = strokeBrush, style = Stroke(width = strokeWidth))
|
||||
}
|
||||
|
||||
// Ambient glow behind the waves — wide, faint, no visible disc edge.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue