Skip to content

Instantly share code, notes, and snippets.

@faogustavo
Last active July 27, 2021 14:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save faogustavo/745c797a47f0a4a7de20f95d86db50b7 to your computer and use it in GitHub Desktop.
Save faogustavo/745c797a47f0a4a7de20f95d86db50b7 to your computer and use it in GitHub Desktop.
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)
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))
)
}
}
}
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