Created
June 10, 2025 12:33
-
-
Save remziakgoz/a5dc14cc73672a8d7802047bb5d31531 to your computer and use it in GitHub Desktop.
Jetpack Compose Wavy Gradient Ring Visualizer π¨
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* A colorful animated ring built with Jetpack Compose Canvas. | |
* Uses sine waves and HSV gradient segments for a smooth, reactive visualization. | |
* Sliders allow you to adjust amplitude and frequency in real time. | |
*/ | |
import androidx.compose.foundation.Canvas | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.layout.Arrangement | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.layout.size | |
import androidx.compose.material3.Slider | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.LaunchedEffect | |
import androidx.compose.runtime.getValue | |
import androidx.compose.runtime.mutableStateOf | |
import androidx.compose.runtime.remember | |
import androidx.compose.runtime.setValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.geometry.Offset | |
import androidx.compose.ui.graphics.Brush | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.graphics.StrokeCap | |
import androidx.compose.ui.unit.dp | |
import kotlinx.coroutines.delay | |
import kotlin.math.PI | |
import kotlin.math.cos | |
import kotlin.math.sin | |
@Composable | |
fun WavyRingVisualizer() { | |
var amplitude by remember { mutableStateOf(0.5f) } | |
var frequency by remember { mutableStateOf(5f) } | |
var time by remember { mutableStateOf(0f) } | |
LaunchedEffect(Unit) { | |
while (true) { | |
time += 0.03f | |
delay(16L) // ~60fps | |
} | |
} | |
Column( | |
modifier = Modifier | |
.fillMaxSize() | |
.background(Color.Black), | |
verticalArrangement = Arrangement.SpaceEvenly, | |
horizontalAlignment = Alignment.CenterHorizontally | |
) { | |
Canvas(modifier = Modifier.size(300.dp)) { | |
val center = Offset(size.width / 2, size.height / 2) | |
val radius = size.minDimension / 2.5f | |
val points = mutableListOf<Offset>() | |
// Generate exactly 360 points for 0 to 359 degrees | |
for (i in 0 until 360) { | |
val angle = (i * 2.0 * PI) / 360.0 // Use 2Ο instead of converting degrees | |
val wave = sin(frequency * angle + time) * amplitude * 20 | |
val r = radius + wave.toFloat() | |
val x = (r * cos(angle)).toFloat() + center.x | |
val y = (r * sin(angle)).toFloat() + center.y | |
points.add(Offset(x, y)) | |
} | |
// Draw as connected line segments, manually connecting each point to the next | |
for (i in points.indices) { | |
val current = points[i] | |
val next = points[(i + 1) % points.size] // Wrap around to first point | |
drawLine( | |
brush = Brush.linearGradient( | |
colors = listOf( | |
Color.hsv((i * 360f / points.size) % 360f, 1f, 1f), | |
Color.hsv(((i + 1) * 360f / points.size) % 360f, 1f, 1f) | |
), | |
start = current, | |
end = next | |
), | |
start = current, | |
end = next, | |
strokeWidth = 6f, | |
cap = StrokeCap.Round | |
) | |
} | |
} | |
Slider( | |
value = amplitude, | |
onValueChange = { amplitude = it }, | |
valueRange = 0f..1f, | |
modifier = Modifier.padding(horizontal = 32.dp) | |
) | |
Slider( | |
value = frequency, | |
onValueChange = { frequency = it }, | |
valueRange = 1f..15f, | |
modifier = Modifier.padding(horizontal = 32.dp) | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment