1 package com.airbnb.lottie.compose 2 3 import com.airbnb.lottie.LottieComposition 4 5 /** 6 * Use subclasses of [LottieClipSpec] to set min/max bounds on the animation playback. 7 * 8 * @see LottieAnimation 9 * @see rememberLottieAnimatable 10 * @see animateLottieCompositionAsState 11 */ 12 sealed class LottieClipSpec { 13 getMinProgressnull14 internal abstract fun getMinProgress(composition: LottieComposition): Float 15 16 internal abstract fun getMaxProgress(composition: LottieComposition): Float 17 18 /** 19 * Play the animation between these two frames. [maxInclusive] determines whether the animation 20 * should play the max frame or stop one frame before it. 21 */ 22 data class Frame( 23 val min: Int? = null, 24 val max: Int? = null, 25 val maxInclusive: Boolean = true, 26 ) : LottieClipSpec() { 27 28 private val actualMaxFrame = when { 29 max == null -> null 30 maxInclusive -> max 31 else -> max - 1 32 } 33 34 override fun getMinProgress(composition: LottieComposition): Float { 35 return when (min) { 36 null -> 0f 37 else -> (min / composition.endFrame).coerceIn(0f, 1f) 38 } 39 } 40 41 override fun getMaxProgress(composition: LottieComposition): Float { 42 return when (actualMaxFrame) { 43 null -> 1f 44 else -> (actualMaxFrame / composition.endFrame).coerceIn(0f, 1f) 45 } 46 } 47 } 48 49 /** 50 * Play the animation between these two progress values. 51 */ 52 data class Progress( 53 val min: Float = 0f, 54 val max: Float = 1f, 55 ) : LottieClipSpec() { getMinProgressnull56 override fun getMinProgress(composition: LottieComposition): Float { 57 return min 58 } 59 getMaxProgressnull60 override fun getMaxProgress(composition: LottieComposition): Float { 61 return max 62 } 63 } 64 65 /** 66 * Play the animation from minMarker until maxMarker. If maxMarker represents the end of your animation, 67 * set [maxInclusive] to true. If the marker represents the beginning of the next section, set 68 * it to false to stop the animation at the frame before maxMarker. 69 */ 70 data class Markers( 71 val min: String? = null, 72 val max: String? = null, 73 val maxInclusive: Boolean = true 74 ) : LottieClipSpec() { getMinProgressnull75 override fun getMinProgress(composition: LottieComposition): Float { 76 return when (min) { 77 null -> 0f 78 else -> ((composition.getMarker(min)?.startFrame ?: 0f) / composition.endFrame).coerceIn(0f, 1f) 79 } 80 } 81 getMaxProgressnull82 override fun getMaxProgress(composition: LottieComposition): Float { 83 return when (max) { 84 null -> 1f 85 else -> { 86 val offset = if (maxInclusive) 0 else -1 87 return ((composition.getMarker(max)?.startFrame?.plus(offset) ?: 0f) / composition.endFrame).coerceIn(0f, 1f) 88 } 89 } 90 } 91 } 92 93 /** 94 * Play the animation from the beginning of the marker for the duration of the marker itself. 95 * The duration can be set in After Effects. 96 */ 97 data class Marker(val marker: String) : LottieClipSpec() { getMinProgressnull98 override fun getMinProgress(composition: LottieComposition): Float { 99 return ((composition.getMarker(marker)?.startFrame ?: 0f) / composition.endFrame).coerceIn(0f, 1f) 100 } 101 getMaxProgressnull102 override fun getMaxProgress(composition: LottieComposition): Float { 103 val marker = composition.getMarker(marker) ?: return 1f 104 return ((marker.startFrame + marker.durationFrames) / composition.endFrame).coerceIn(0f, 1f) 105 } 106 } 107 }