What You Will Build
A pulsing, glowing orb with orbiting particle dots and a radial gradient glow effect. The orb breathes (scales up and down) while 30 particles orbit around it in a ring. Perfect for loading states, meditation apps, or sci-fi themed UIs.
Why This Pattern Matters
Radial gradient glows and orbiting particles are staples of modern UI design. This project teaches Brush.radialGradient for glow effects, trigonometric positioning for orbital layouts, and multi-property infinite transitions.
Step 1: Two Infinite Animations
@Composable
fun OrbAnimationScreen() {
val infiniteTransition = rememberInfiniteTransition(label = "orb")
val phase by infiniteTransition.animateFloat(
0f, 360f,
infiniteRepeatable(tween(4000, easing = LinearEasing)),
label = "phase"
)
val pulse by infiniteTransition.animateFloat(
0.8f, 1.2f,
infiniteRepeatable(tween(2000), RepeatMode.Reverse),
label = "pulse"
)
// ...
}
Step 2: Draw Glow, Particles, and Core
Canvas(Modifier.size(300.dp)) {
val center = Offset(size.width / 2, size.height / 2)
// Outer glow
drawCircle(
Brush.radialGradient(
listOf(Color(0xFF4ECDC4).copy(alpha = 0.3f),
Color.Transparent),
center, 200f * pulse
),
200f * pulse, center
)
// Orbiting particles
for (i in 0 until 30) {
val angle = Math.toRadians((i * 12.0 + phase).toDouble())
val r = 100f * pulse
val x = center.x + r * cos(angle).toFloat()
val y = center.y + r * sin(angle).toFloat()
drawCircle(
Color(0xFF4ECDC4).copy(alpha = 0.6f),
3f, Offset(x, y)
)
}
// Core orb
drawCircle(
Brush.radialGradient(
listOf(Color(0xFF4ECDC4), Color(0xFF1A8A7D),
Color.Transparent),
center, 60f * pulse
),
60f * pulse, center
)
}
Tips and Pitfalls
- Layer order matters: Draw glow first (background), then particles (middle), then core (foreground). Reversing makes the glow cover the particles.
- 30 particles at 12-degree intervals fills a complete 360-degree ring. Adjust count and spacing for denser or sparser rings.
- pulse multiplier (0.8-1.2) creates a 40% size oscillation. The same multiplier applied to glow radius, particle orbit radius, and core radius keeps everything breathing in sync.
- Add more rings: Use multiple loops with different radii and phase offsets for a more complex effect.