Skip to content

Instantly share code, notes, and snippets.

@belinwu
Forked from riggaroo/KeyframesWithSpline.kt
Created December 18, 2024 04:27
Show Gist options
  • Save belinwu/f308146bbcc1dfaf891239750aaf1766 to your computer and use it in GitHub Desktop.
Save belinwu/f308146bbcc1dfaf891239750aaf1766 to your computer and use it in GitHub Desktop.
KeyframesWithSpline Example
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.VectorConverter
import androidx.compose.animation.core.animateValue
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.keyframesWithSpline
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.PointMode
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.boundsInParent
import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
@Preview
@Composable
fun SlaySantaSlay() {
val points = remember { mutableStateListOf<Offset>() }
val infiniteTransition = rememberInfiniteTransition()
BoxWithConstraints (modifier = Modifier.fillMaxSize()) {
val santaSize = with(LocalDensity.current){
100.dp.toPx()
}
val maxSantaX = with (LocalDensity.current) {
maxWidth.toPx() - santaSize
}
val maxSantaY = with(LocalDensity.current){
maxHeight.toPx() - santaSize
}
val offset = infiniteTransition.animateValue(
initialValue = Offset(santaSize, santaSize),
targetValue = Offset(maxSantaX *1.5f, maxSantaY * 0.3f),
typeConverter = Offset.VectorConverter,
animationSpec = infiniteRepeatable(
animation = keyframesWithSpline {
durationMillis = 6000
Offset(santaSize, santaSize) at 0
Offset(maxSantaX * 0.5f, maxSantaY * 0.2f) atFraction 0.1f
Offset(maxSantaX - santaSize, maxSantaY * 0.3f) atFraction 0.3f
Offset(santaSize, maxSantaY * 0.5f) atFraction 0.4f
Offset(maxSantaX * 0.4f, maxSantaY * 0.6f) atFraction 0.5f
Offset(maxSantaX * 0.1f, maxSantaY * 0.7f) atFraction 0.6f
Offset(maxSantaX * 0.3f, maxSantaY * 0.8f) atFraction 0.7f
},
repeatMode = RepeatMode.Restart))
Image(painter = painterResource(id = R.drawable.background),
contentDescription = "Santa",
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop)
Box(modifier = Modifier.fillMaxSize()
.drawBehind {
drawPoints(
points = points,
pointMode = PointMode.Lines,
color = Color.LightGray,
strokeWidth = 4f,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(30f, 20f))
)
})
Image(painter = painterResource(id = R.drawable.santa),
contentDescription = "Santa",
modifier = Modifier.size(100.dp)
.offset { offset.value.round() }
.onPlaced { points.add(it.boundsInParent().center) }
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment