Last active
July 27, 2021 14:51
-
-
Save faogustavo/745c797a47f0a4a7de20f95d86db50b7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.compose.animation.core.CubicBezierEasing | |
// Sine Easing | |
// https://easings.net/#easeInSine | |
val EaseInSine = CubicBezierEasing(0.12f, 0f, 0.39f, 0f) | |
// https://easings.net/#easeOutSine | |
val EaseOutSine = CubicBezierEasing(0.61f, 1f, 0.88f, 1f) | |
// https://easings.net/#easeInOutSine | |
val EaseInOutSine = CubicBezierEasing(0.37f, 0f, 0.63f, 1f) | |
// Quad Easing | |
// https://easings.net/#easeInQuad | |
val EaseInQuad = CubicBezierEasing(0.11f, 0f, 0.5f, 0f) | |
// https://easings.net/#easeOutQuad | |
val EaseOutQuad = CubicBezierEasing(0.5f, 1f, 0.89f, 1f) | |
// https://easings.net/#easeInOutQuad | |
val EaseInOutQuad = CubicBezierEasing(0.45f, 0f, 0.55f, 1f) | |
// Cubic Easing | |
// https://easings.net/#easeInCubic | |
val EaseInCubic = CubicBezierEasing(0.32f, 0f, 0.67f, 0f) | |
// https://easings.net/#easeOutCubic | |
val EaseOutCubic = CubicBezierEasing(0.33f, 1f, 0.68f, 1f) | |
// https://easings.net/#easeInOutCubic | |
val EaseInOutCubic = CubicBezierEasing(0.65f, 0f, 0.35f, 1f) | |
// Quart Easing | |
// https://easings.net/#easeInQuart | |
val EaseInQuart = CubicBezierEasing(0.5f, 0f, 0.75f, 0f) | |
// https://easings.net/#easeOutQuart | |
val EaseOutQuart = CubicBezierEasing(0.25f, 1f, 0.5f, 1f) | |
// https://easings.net/#easeInOutQuart | |
val EaseInOutQuart = CubicBezierEasing(0.76f, 0f, 0.24f, 1f) | |
// Quint Easing | |
// https://easings.net/#easeInQuint | |
val EaseInQuint = CubicBezierEasing(0.64f, 0f, 0.78f, 0f) | |
// https://easings.net/#easeOutQuint | |
val EaseOutQuint = CubicBezierEasing(0.22f, 1f, 0.36f, 1f) | |
// https://easings.net/#easeInOutQuint | |
val EaseInOutQuint = CubicBezierEasing(0.83f, 0f, 0.17f, 1f) | |
// Expo Easing | |
// https://easings.net/#easeInExpo | |
val EaseInExpo = CubicBezierEasing(0.7f, 0f, 0.84f, 0f) | |
// https://easings.net/#easeOutExpo | |
val EaseOutExpo = CubicBezierEasing(0.16f, 1f, 0.3f, 1f) | |
// https://easings.net/#easeInOutExpo | |
val EaseInOutExpo = CubicBezierEasing(0.87f, 0f, 0.13f, 1f) | |
// Circ Easing | |
// https://easings.net/#easeInCirc | |
val EaseInCirc = CubicBezierEasing(0.55f, 0f, 1f, 0.45f) | |
// https://easings.net/#easeOutCirc | |
val EaseOutCirc = CubicBezierEasing(0f, 0.55f, 0.45f, 1f) | |
// https://easings.net/#easeInOutCirc | |
val EaseInOutCirc = CubicBezierEasing(0.85f, 0f, 0.15f, 1f) | |
// Back Easing | |
// https://easings.net/#easeInBack | |
val EaseInBack = CubicBezierEasing(0.36f, 0f, 0.66f, -0.56f) | |
// https://easings.net/#easeOutBack | |
val EaseOutBack = CubicBezierEasing(0.34f, 1.56f, 0.64f, 1f) | |
// https://easings.net/#easeInOutBack | |
val EaseInOutBack = CubicBezierEasing(0.68f, -0.6f, 0.32f, 1.6f) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.compose.animation.core.* | |
import androidx.compose.foundation.Canvas | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.layout.height | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.lazy.LazyColumn | |
import androidx.compose.foundation.lazy.items | |
import androidx.compose.material.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.geometry.Offset | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.text.font.FontWeight | |
import androidx.compose.ui.unit.dp | |
val ALL_EASIGNS = mapOf( | |
"LinearEasing (Compose)" to LinearEasing, | |
"FastOutSlowInEasing (Compose)" to FastOutSlowInEasing, | |
"LinearOutSlowInEasing (Compose)" to LinearOutSlowInEasing, | |
"FastOutLinearInEasing (Compose)" to FastOutLinearInEasing, | |
"EaseInSine" to EaseInSine, | |
"EaseOutSine" to EaseOutSine, | |
"EaseInOutSine" to EaseInOutSine, | |
"EaseInQuad" to EaseInQuad, | |
"EaseOutQuad" to EaseOutQuad, | |
"EaseInOutQuad" to EaseInOutQuad, | |
"EaseInCubic" to EaseInCubic, | |
"EaseOutCubic" to EaseOutCubic, | |
"EaseInOutCubic" to EaseInOutCubic, | |
"EaseInQuart" to EaseInQuart, | |
"EaseOutQuart" to EaseOutQuart, | |
"EaseInOutQuart" to EaseInOutQuart, | |
"EaseInQuint" to EaseInQuint, | |
"EaseOutQuint" to EaseOutQuint, | |
"EaseInOutQuint" to EaseInOutQuint, | |
"EaseInExpo" to EaseInExpo, | |
"EaseOutExpo" to EaseOutExpo, | |
"EaseInOutExpo" to EaseInOutExpo, | |
"EaseInCirc" to EaseInCirc, | |
"EaseOutCirc" to EaseOutCirc, | |
"EaseInOutCirc" to EaseInOutCirc, | |
"EaseInBack" to EaseInBack, | |
"EaseOutBack" to EaseOutBack, | |
"EaseInOutBack" to EaseInOutBack, | |
"EaseInElastic" to EaseInElastic, | |
"EaseOutElastic" to EaseOutElastic, | |
"EaseInOutElastic" to EaseInOutElastic, | |
"EaseInBounce" to EaseInBounce, | |
"EaseOutBounce" to EaseOutBounce, | |
"EaseInOutBounce" to EaseInOutBounce, | |
) | |
@Composable | |
fun EasingDemo() { | |
LazyColumn { | |
items(ALL_EASIGNS.toList()) { (name, easing) -> | |
Graph( | |
name = name, | |
easingFunction = easing | |
) | |
} | |
} | |
} | |
@Composable | |
fun Graph( | |
name: String, | |
easingFunction: Easing, | |
) { | |
val infiniteTransition = rememberInfiniteTransition() | |
val time by infiniteTransition.animateFloat( | |
initialValue = 0f, | |
targetValue = 1f, | |
animationSpec = infiniteRepeatable( | |
animation = tween( | |
durationMillis = 2500, | |
easing = LinearEasing, | |
) | |
) | |
) | |
val value by infiniteTransition.animateFloat( | |
initialValue = 0f, | |
targetValue = 1f, | |
animationSpec = infiniteRepeatable( | |
animation = tween( | |
durationMillis = 2500, | |
easing = easingFunction, | |
) | |
) | |
) | |
Column( | |
horizontalAlignment = Alignment.CenterHorizontally, | |
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp) | |
) { | |
Text( | |
text = name, | |
fontWeight = FontWeight.Bold, | |
modifier = Modifier.padding(bottom = 8.dp) | |
) | |
Canvas( | |
modifier = Modifier | |
.fillMaxWidth() | |
.height(200.dp) | |
) { | |
val canvasWidth = size.width | |
val canvasHeight = size.height | |
drawLine( | |
color = Color.Blue, | |
strokeWidth = 3f, | |
start = Offset.Zero, | |
end = Offset(0f, canvasHeight), | |
) | |
drawLine( | |
color = Color.Blue, | |
strokeWidth = 3f, | |
start = Offset(canvasWidth, 0f), | |
end = Offset(canvasWidth, canvasHeight), | |
) | |
drawLine( | |
color = Color.Red, | |
strokeWidth = 3f, | |
start = Offset(0f, canvasHeight), | |
end = Offset(canvasWidth, canvasHeight), | |
) | |
drawLine( | |
color = Color.Red, | |
strokeWidth = 3f, | |
start = Offset(0f, 0f), | |
end = Offset(canvasWidth, 0f), | |
) | |
val canvasSizeInt = canvasWidth.toInt() | |
for (i in 1..canvasSizeInt) { | |
val currentTime = (i + 1) / canvasSizeInt.toFloat() | |
val previousTime = (i - 1) / canvasSizeInt.toFloat() | |
drawLine( | |
color = Color.LightGray, | |
strokeWidth = 2f, | |
start = Offset( | |
x = canvasWidth * previousTime, | |
y = canvasHeight * (1 - easingFunction.transform(previousTime)) | |
), | |
end = Offset( | |
x = canvasWidth * currentTime, | |
y = canvasHeight * (1 - easingFunction.transform(currentTime)) | |
), | |
) | |
} | |
drawCircle( | |
color = Color.Black, | |
radius = 10f, | |
center = Offset(canvasWidth * time, canvasHeight * (1 - value)) | |
) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.compose.animation.core.Easing | |
import kotlin.math.* | |
// Sine Easing | |
// https://easings.net/#easeInSine | |
object EaseInSine : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - cos((fraction * PI.toFloat()) / 2) | |
} | |
// https://easings.net/#easeOutSine | |
object EaseOutSine : Easing { | |
override fun transform(fraction: Float): Float = | |
sin((fraction * PI.toFloat()) / 2) | |
} | |
// https://easings.net/#easeInOutSine | |
object EaseInOutSine : Easing { | |
override fun transform(fraction: Float): Float = | |
-(cos(fraction * PI.toFloat()) - 1) / 2 | |
} | |
// Quad Easing | |
// https://easings.net/#easeInQuad | |
object EaseInQuad : Easing { | |
override fun transform(fraction: Float): Float = | |
fraction.pow(2) | |
} | |
// https://easings.net/#easeOutQuad | |
object EaseOutQuad : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - (1 - fraction).pow(2) | |
} | |
// https://easings.net/#easeInOutQuad | |
object EaseInOutQuad : Easing { | |
override fun transform(fraction: Float): Float = if (fraction < 0.5f) { | |
2 * fraction.pow(2) | |
} else { | |
1 - (-2 * fraction + 2).pow(2) / 2 | |
} | |
} | |
// Cubic Easing | |
// https://easings.net/#easeInCubic | |
object EaseInCubic : Easing { | |
override fun transform(fraction: Float): Float = | |
fraction.pow(3) | |
} | |
// https://easings.net/#easeOutCubic | |
object EaseOutCubic : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - (1 - fraction).pow(3) | |
} | |
// https://easings.net/#easeInOutCubic | |
object EaseInOutCubic : Easing { | |
override fun transform(fraction: Float): Float = if (fraction < 0.5f) { | |
4 * fraction.pow(3) | |
} else { | |
1 - (-2 * fraction + 2).pow(3) / 2 | |
} | |
} | |
// Quart Easing | |
// https://easings.net/#easeInQuart | |
object EaseInQuart : Easing { | |
override fun transform(fraction: Float): Float = | |
fraction.pow(4) | |
} | |
// https://easings.net/#easeOutQuart | |
object EaseOutQuart : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - (1 - fraction).pow(4) | |
} | |
// https://easings.net/#easeInOutQuart | |
object EaseInOutQuart : Easing { | |
override fun transform(fraction: Float): Float = if (fraction < 0.5f) { | |
8 * fraction.pow(4) | |
} else { | |
1 - (-2 * fraction + 2).pow(4) / 2 | |
} | |
} | |
// Quint Easing | |
// https://easings.net/#easeInQuint | |
object EaseInQuint : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - (1 - fraction).pow(5) | |
} | |
// https://easings.net/#easeOutQuint | |
object EaseOutQuint : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - (1 - fraction).pow(5) | |
} | |
// https://easings.net/#easeInOutQuint | |
object EaseInOutQuint : Easing { | |
override fun transform(fraction: Float): Float = if (fraction < 0.5f) { | |
16 * fraction.pow(5) | |
} else { | |
1 - (-2 * fraction + 2).pow(5) / 2 | |
} | |
} | |
// Expo Easing | |
// https://easings.net/#easeInExpo | |
object EaseInExpo : Easing { | |
override fun transform(fraction: Float): Float = | |
if (fraction == 0f) fraction else 2f.pow(10 * fraction - 10) | |
} | |
// https://easings.net/#easeOutExpo | |
object EaseOutExpo : Easing { | |
override fun transform(fraction: Float): Float = | |
if (fraction == 1f) fraction else (1 - 2f.pow(-10 * fraction)) | |
} | |
// https://easings.net/#easeInOutExpo | |
object EaseInOutExpo : Easing { | |
override fun transform(fraction: Float): Float = when { | |
fraction == 0f || fraction == 1f -> fraction | |
fraction < 0.5f -> 2f.pow(20 * fraction - 10) / 2 | |
else -> (2 - 2f.pow(-20 * fraction + 10)) / 2 | |
} | |
} | |
// Circ Easing | |
// https://easings.net/#easeInCirc | |
object EaseInCirc : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - sqrt(1 - fraction.pow(2)) | |
} | |
// https://easings.net/#easeOutCirc | |
object EaseOutCirc : Easing { | |
override fun transform(fraction: Float): Float = | |
sqrt(1 - (fraction - 1).pow(2)) | |
} | |
// https://easings.net/#easeInOutCirc | |
object EaseInOutCirc : Easing { | |
override fun transform(fraction: Float): Float = if (fraction < 0.5f) { | |
(1 - sqrt(1 - (2 * fraction).pow(2))) / 2 | |
} else { | |
(sqrt(1 - (-2 * fraction + 2).pow(2)) + 1) / 2 | |
} | |
} | |
// Back Easing | |
// https://easings.net/#easeInBack | |
object EaseInBack : Easing { | |
override fun transform(fraction: Float): Float { | |
val c1 = 1.70158f | |
val c3 = c1 + 1 | |
return c3 * fraction.pow(3) - c1 * fraction.pow(2) | |
} | |
} | |
// https://easings.net/#easeOutBack | |
object EaseOutBack : Easing { | |
override fun transform(fraction: Float): Float { | |
val c1 = 1.70158f | |
val c3 = c1 + 1 | |
return 1 + c3 * (fraction - 1).pow(3) + c1 * (fraction - 1).pow(2) | |
} | |
} | |
// https://easings.net/#easeInOutBack | |
object EaseInOutBack : Easing { | |
override fun transform(fraction: Float): Float { | |
val c1 = 1.70158f | |
val c2 = c1 * 1.525f | |
return if (fraction < 0.5f) { | |
((2 * fraction).pow(2) * ((c2 + 1) * 2 * fraction - c2)) / 2 | |
} else { | |
((2 * fraction - 2).pow(2) * ((c2 + 1) * (fraction * 2 - 2) + c2) + 2) / 2 | |
} | |
} | |
} | |
// https://easings.net/#easeInElastic | |
object EaseInElastic : Easing { | |
override fun transform(fraction: Float): Float { | |
val c4: Float = (2 * PI.toFloat()) / 3 | |
return if (fraction == 0f || fraction == 1f) { | |
fraction | |
} else { | |
-(2f.pow(10 * fraction - 10)) * sin((fraction * 10 - 10.75f) * c4) | |
} | |
} | |
} | |
// https://easings.net/#easeOutElastic | |
object EaseOutElastic : Easing { | |
override fun transform(fraction: Float): Float { | |
val c4: Float = (2 * PI.toFloat()) / 3 | |
return if (fraction == 0f || fraction == 1f) { | |
fraction | |
} else { | |
2f.pow(-10 * fraction) * sin((fraction * 10 - 0.75f) * c4) + 1 | |
} | |
} | |
} | |
// https://easings.net/#easeInOutElastic | |
object EaseInOutElastic : Easing { | |
override fun transform(fraction: Float): Float { | |
val c5: Float = (2 * PI.toFloat()) / 4.5f | |
return when { | |
fraction == 0f || fraction == 1f -> fraction | |
fraction < 0.5f -> -(2f.pow(20 * fraction - 10) * sin((20 * fraction - 11.125f) * c5)) / 2 | |
else -> (2f.pow(-20 * fraction + 10) * sin((20 * fraction - 11.125f) * c5)) / 2 + 1 | |
} | |
} | |
} | |
// https://easings.net/#easeInBounce | |
object EaseInBounce : Easing { | |
override fun transform(fraction: Float): Float = | |
1 - EaseOutBounce.transform(1 - fraction) | |
} | |
// https://easings.net/#easeOutBounce | |
object EaseOutBounce : Easing { | |
override fun transform(fraction: Float): Float { | |
val n1 = 7.5625f | |
val d1 = 2.75f | |
return when { | |
fraction < (1f / d1) -> n1 * fraction.pow(2) | |
fraction < (2f / d1) -> { | |
val fractionSub = fraction - (1.5f / d1) | |
n1 * fractionSub.pow(2) + 0.75f | |
} | |
fraction < (2.5f / d1) -> { | |
val fractionSub = fraction - (2.25f / d1) | |
n1 * fractionSub.pow(2) + 0.9375f | |
} | |
else -> { | |
val fractionSub = fraction - (2.625f / d1) | |
n1 * fractionSub.pow(2) + 0.984375f | |
} | |
} | |
} | |
} | |
// https://easings.net/#easeInOutBounce | |
object EaseInOutBounce : Easing { | |
override fun transform(fraction: Float): Float = if (fraction < 0.5f) { | |
(1 - EaseOutBounce.transform(1 - 2 * fraction)) / 2 | |
} else { | |
(1 + EaseOutBounce.transform(2 * fraction - 1)) / 2 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment