Skip to content

Instantly share code, notes, and snippets.

@Kyriakos-Georgiopoulos
Last active October 28, 2025 11:10
Show Gist options
  • Select an option

  • Save Kyriakos-Georgiopoulos/3d1b22e4e7e24f6a2a529faa54c94850 to your computer and use it in GitHub Desktop.

Select an option

Save Kyriakos-Georgiopoulos/3d1b22e4e7e24f6a2a529faa54c94850 to your computer and use it in GitHub Desktop.
/*
* Copyright 2025 Kyriakos Georgiopoulos
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.lerp
import androidx.compose.ui.graphics.lerp as colorLerp
@Composable
fun TimeRemapDemo() {
val t = remember { Animatable(0f) }
LaunchedEffect(Unit) {
while (true) {
t.animateTo(1f, tween(1600, easing = LinearEasing))
t.animateTo(0f, tween(1600, easing = LinearEasing))
}
}
val base = t.value
fun lead(f: Float, amount: Float = 0.1f) = (f * (1f + amount)).coerceIn(0f, 1f)
fun lag(f: Float, amount: Float = 0.15f) = (f * (1f - amount)).coerceIn(0f, 1f)
fun pause(f: Float, holdStart: Float = 0.35f, holdEnd: Float = 0.55f): Float =
when {
f <= holdStart -> f / holdStart * holdStart
f <= holdEnd -> holdStart
else -> {
val rem = 1f - holdEnd
holdStart + ((f - holdEnd) / rem) * (1f - holdStart)
}
}
val posT = FastOutSlowInEasing.transform(lead(base))
val colorT = LinearOutSlowInEasing.transform(lag(pause(base)))
val startColor = Color(0xFF5B86E5)
val endColor = Color(0xFF36D1DC)
val boxColor = colorLerp(startColor, endColor, colorT)
val boxWidth = 200.dp
val boxHeight = 56.dp
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF0F1115)),
contentAlignment = Alignment.Center
) {
BoxWithConstraints(
modifier = Modifier
.fillMaxWidth()
.height(boxHeight) // the track
) {
val travel = (maxWidth - boxWidth).coerceAtLeast(0.dp)
val x = lerp(0.dp, travel, posT)
Box(
modifier = Modifier
.offset(x = x)
.size(boxWidth, boxHeight)
.padding(horizontal = 12.dp)
.clip(RoundedCornerShape(16.dp))
.background(boxColor)
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment