feat: add dynamic blur effect to avatar based on proximity to notch in ProfileMetaballOverlay
This commit is contained in:
@@ -260,6 +260,16 @@ fun ProfileMetaballOverlay(
|
||||
// Should we draw the connector? (when avatar gets close enough)
|
||||
val showConnector = collapseProgress > 0.3f && avatarState.showBlob && distance < maxDist * 2f
|
||||
|
||||
// Calculate blur intensity for avatar based on distance to notch (like Telegram)
|
||||
// When avatar is far - no blur, when close - more blur
|
||||
val avatarBlurRadius = if (showConnector) {
|
||||
// More blur as avatar gets closer to notch
|
||||
val nearProgress = (1f - (distance / maxDist).coerceIn(0f, 1f))
|
||||
(nearProgress * ProfileMetaballConstants.BLUR_RADIUS * 0.5f).coerceIn(0f, 10f)
|
||||
} else {
|
||||
0f
|
||||
}
|
||||
|
||||
Box(modifier = modifier.fillMaxSize()) {
|
||||
// LAYER 1: Metaball shapes with blur effect (BLACK shapes only)
|
||||
Canvas(
|
||||
@@ -267,18 +277,16 @@ fun ProfileMetaballOverlay(
|
||||
.fillMaxSize()
|
||||
.graphicsLayer {
|
||||
metaShader.setFloatUniform("cutoff", ProfileMetaballConstants.CUTOFF)
|
||||
renderEffect = RenderEffect
|
||||
.createBlurEffect(
|
||||
ProfileMetaballConstants.BLUR_RADIUS,
|
||||
ProfileMetaballConstants.BLUR_RADIUS,
|
||||
Shader.TileMode.DECAL
|
||||
)
|
||||
.let { blurEffect ->
|
||||
RenderEffect.createChainEffect(
|
||||
RenderEffect.createRuntimeShaderEffect(metaShader, "composable"),
|
||||
blurEffect
|
||||
)
|
||||
}
|
||||
// IMPORTANT: First blur, THEN threshold shader
|
||||
// createChainEffect(outer, inner) - inner is applied first
|
||||
val blurEffect = RenderEffect.createBlurEffect(
|
||||
ProfileMetaballConstants.BLUR_RADIUS,
|
||||
ProfileMetaballConstants.BLUR_RADIUS,
|
||||
Shader.TileMode.DECAL
|
||||
)
|
||||
val thresholdEffect = RenderEffect.createRuntimeShaderEffect(metaShader, "composable")
|
||||
// Chain: blur first (inner), then threshold (outer)
|
||||
renderEffect = RenderEffect.createChainEffect(thresholdEffect, blurEffect)
|
||||
.asComposeRenderEffect()
|
||||
}
|
||||
) {
|
||||
@@ -343,7 +351,7 @@ fun ProfileMetaballOverlay(
|
||||
}
|
||||
}
|
||||
|
||||
// LAYER 2: Actual avatar content (NO BLUR!) - rendered on top
|
||||
// LAYER 2: Actual avatar content - with blur when close to notch
|
||||
if (avatarState.showBlob) {
|
||||
val avatarSizeDp = with(density) { (avatarState.radius * 2f).toDp() }
|
||||
val avatarOffsetX = with(density) { (avatarState.centerX - avatarState.radius).toDp() }
|
||||
@@ -357,6 +365,14 @@ fun ProfileMetaballOverlay(
|
||||
.clip(RoundedCornerShape(avatarSizeDp / 2))
|
||||
.graphicsLayer {
|
||||
alpha = avatarState.opacity
|
||||
// Apply blur to avatar when close to notch (like Telegram)
|
||||
if (avatarBlurRadius > 0.5f) {
|
||||
renderEffect = RenderEffect.createBlurEffect(
|
||||
avatarBlurRadius,
|
||||
avatarBlurRadius,
|
||||
Shader.TileMode.DECAL
|
||||
).asComposeRenderEffect()
|
||||
}
|
||||
},
|
||||
contentAlignment = Alignment.Center,
|
||||
content = avatarContent
|
||||
|
||||
Reference in New Issue
Block a user