Skip to content

Commit

Permalink
composition properties
Browse files Browse the repository at this point in the history
  • Loading branch information
alexzhirkevich committed Dec 12, 2023
1 parent 8df0dca commit ed6c3e0
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 46 deletions.
10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,22 @@ Basic usage:

val lottieData : String = // ... your lottie JSON

val composition = rememberLottieComposition(lottieData)
val composition by rememberLottieComposition(lottieData)

LottieAnimation(
composition = composition,
modifier = Modifier.size(300.dp)
)
```

With manual progress control:
```kotlin
val composition = rememberLottieComposition(lottieData)
val composition by rememberLottieComposition(lottieData)

val progress = animateLottieCompositionAsState(composition)
val progress by animateLottieCompositionAsState(composition)

LottieAnimation(
composition = composition,
progress = { progress.value },
modifier = Modifier.size(300.dp)
progress = { progress },
)
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ package io.github.alexzhirkevich.compottie

import androidx.compose.animation.core.RepeatMode
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import com.airbnb.lottie.Lottie
import com.airbnb.lottie.compose.LottieCancellationBehavior
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.animateLottieCompositionAsState
Expand All @@ -14,44 +20,59 @@ import com.airbnb.lottie.compose.rememberLottieComposition


actual class LottieComposition(
internal val composition : com.airbnb.lottie.LottieComposition?
)
internal val composition : com.airbnb.lottie.LottieComposition
) {

actual val frameRate: Float
get() = composition.frameRate

actual val duration: Float
get() = composition.duration / 1000
}

//actual val LottieComposition.duration : Float
// get() = duration / 1000f

@Composable
actual fun rememberLottieComposition(data : String) : LottieComposition {
val composition = rememberLottieComposition(LottieCompositionSpec.JsonString(data)).value
actual fun rememberLottieComposition(data : String) : State<LottieComposition?> {

return remember(composition) {
LottieComposition(composition)
val state = remember {
mutableStateOf<LottieComposition?>(null)
}

val composition by rememberLottieComposition(LottieCompositionSpec.JsonString(data))

LaunchedEffect(composition) {
// composition?.b
state.value = composition?.let(::LottieComposition)
}

return state
}

@Composable
actual fun LottieAnimation(
composition : LottieComposition,
composition : LottieComposition?,
progress : () -> Float,
modifier: Modifier,
) {
com.airbnb.lottie.compose.LottieAnimation(
modifier = modifier,
composition = composition.composition,
composition = composition?.composition,
progress = progress
)
}

@Composable
actual fun animateLottieCompositionAsState(
composition: LottieComposition,
composition: LottieComposition?,
repeatMode: RepeatMode,
cancellationBehavior: CancellationBehavior,
isPlaying : Boolean,
iterations : Int,
) : State<Float> {
return animateLottieCompositionAsState(
composition = composition.composition,
composition = composition?.composition,
reverseOnRepeat = repeatMode == RepeatMode.Reverse,
iterations = iterations,
restartOnPlay = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.animation.core.RepeatMode
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size

enum class CancellationBehavior {
/**
Expand All @@ -22,7 +23,19 @@ enum class CancellationBehavior {
/**
* Holds animation data
* */
expect class LottieComposition
expect class LottieComposition {

/**
* Animation frame per second rate
* */

val frameRate : Float

/**
* Animation duration in seconds
* */
val duration : Float
}

///**
// * Animation duration in seconds
Expand All @@ -35,7 +48,7 @@ expect class LottieComposition
* @param data Lottie JSON string
* */
@Composable
expect fun rememberLottieComposition(data : String) : LottieComposition
expect fun rememberLottieComposition(data : String) : State<LottieComposition?>

/**
* State of the lottie animation progress
Expand All @@ -51,7 +64,7 @@ expect fun rememberLottieComposition(data : String) : LottieComposition
* */
@Composable
expect fun animateLottieCompositionAsState(
composition: LottieComposition,
composition: LottieComposition?,
repeatMode: RepeatMode = RepeatMode.Restart,
cancellationBehavior: CancellationBehavior = CancellationBehavior.Immediately,
isPlaying : Boolean = true,
Expand All @@ -69,7 +82,7 @@ expect fun animateLottieCompositionAsState(
* */
@Composable
expect fun LottieAnimation(
composition : LottieComposition,
composition : LottieComposition?,
progress : () -> Float,
modifier: Modifier = Modifier
)
Expand All @@ -88,7 +101,7 @@ expect fun LottieAnimation(
* */
@Composable
fun LottieAnimation(
composition: LottieComposition,
composition: LottieComposition?,
modifier: Modifier = Modifier,
repeatMode: RepeatMode = RepeatMode.Restart,
cancellationBehavior: CancellationBehavior = CancellationBehavior.Immediately,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,26 @@ import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.repeatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.DpSize
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.takeWhile
Expand All @@ -30,49 +37,72 @@ import org.jetbrains.skia.skottie.Animation
import org.jetbrains.skia.sksg.InvalidationController
import kotlin.math.roundToInt

actual typealias LottieComposition = Animation
actual class LottieComposition(internal val animation: Animation) {
actual val frameRate: Float
get() = animation.fPS

/**
* Animation duration in seconds
* */
actual val duration: Float
get() = animation.duration
}

//actual val LottieComposition.duration : Float
// get() = duration

@Composable
actual fun rememberLottieComposition(data : String) : LottieComposition {
return remember(data) { Animation.makeFromString(data) }
actual fun rememberLottieComposition(data : String) : State<LottieComposition?> {
return remember(data) { mutableStateOf(LottieComposition(Animation.makeFromString(data))) }
}

@Composable
actual fun LottieAnimation(
composition : LottieComposition,
composition : LottieComposition?,
progress : () -> Float,
modifier: Modifier
) {

val animation = composition ?: return
val defaultSize = LocalDensity.current.run {
if (composition == null)
DpSize.Zero
else
DpSize(
composition.animation.width.toDp(),
composition.animation.height.toDp(),
)
}


val invalidationController = remember { InvalidationController() }

Canvas(modifier) {
Canvas(
modifier
.size(defaultSize)
) {
drawIntoCanvas {
animation.seek(progress(), invalidationController)
if (composition != null) {
composition.animation.seek(progress(), invalidationController)

animation.render(
canvas = it.nativeCanvas,
dst = Rect.makeWH(size.width, size.height)
)
composition.animation.render(
canvas = it.nativeCanvas,
dst = Rect.makeWH(size.width, size.height)
)
}
}
}
}

@Composable
actual fun animateLottieCompositionAsState(
composition: LottieComposition,
composition: LottieComposition?,
repeatMode: RepeatMode,
cancellationBehavior: CancellationBehavior,
isPlaying : Boolean,
iterations : Int,
) : State<Float> {

val duration = composition.duration.times(1000).roundToInt()
val duration = composition?.animation?.duration?.times(1000)?.roundToInt() ?: 0
val animationSpec = tween<Float>(duration, easing = LinearEasing)

val progress = remember {
Expand Down
30 changes: 18 additions & 12 deletions example/shared/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import io.github.alexzhirkevich.compottie.LottieAnimation
import io.github.alexzhirkevich.compottie.animateLottieCompositionAsState
import io.github.alexzhirkevich.compottie.rememberLottieComposition

private const val lottieData = """
Expand All @@ -20,21 +26,21 @@ fun App() {
contentAlignment = Alignment.Center
) {

val composition = rememberLottieComposition(lottieData)
val composition by rememberLottieComposition(lottieData)

// val progress = animateLottieCompositionAsState(
// cancellationBehavior = LottieCancellationBehavior.OnIterationFinish,
// composition = composition,
// repeatMode = RepeatMode.Restart,
// iterations = Int.MAX_VALUE
// )
val progress = animateLottieCompositionAsState(composition)

println("LOTTIE DATA ${composition?.size}")

LottieAnimation(
composition = composition,
// progress = { progress.value },
modifier = Modifier.size(300.dp)
)
Row {
repeat(3) {
LottieAnimation(
composition = composition,
progress = { progress.value },
modifier = Modifier.border(1.dp, Color.Blue)
)
}
}
}
}

0 comments on commit ed6c3e0

Please sign in to comment.