Created
June 1, 2022 09:52
-
-
Save dilrajsingh1997/4af260b223c584a71fcf5f95f05711bc 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
fun getPathCanvasObject() = CanvasPath( | |
path = Path().apply { | |
heartPath(Size(120f, 120f)) | |
}, | |
) | |
fun getTextCanvasObject(text: String = "hi") = | |
CanvasText(text) { | |
color = android.graphics.Color.WHITE | |
isAntiAlias = true | |
textSize = 48f | |
typeface = | |
android.graphics.Typeface.create(android.graphics.Typeface.DEFAULT, | |
android.graphics.Typeface.BOLD) | |
} | |
class SinWaveAnimationSpec( | |
val durationMillis: Int = AnimationConstants.DefaultDurationMillis, | |
val delay: Int = 0, | |
val easing: Easing = FastOutSlowInEasing, | |
val multiplier: Int = 100, | |
) : DurationBasedAnimationSpec<Float> { | |
override fun <V : AnimationVector> vectorize(converter: TwoWayConverter<Float, V>): VectorizedDurationBasedAnimationSpec<V> = | |
object : VectorizedDurationBasedAnimationSpec<V> { | |
private val anim = VectorizedFloatAnimationSpec<V>( | |
SinWaveSpec(durationMillis, delayMillis, easing, multiplier) | |
) | |
override fun getValueFromNanos( | |
playTimeNanos: Long, | |
initialValue: V, | |
targetValue: V, | |
initialVelocity: V, | |
): V { | |
return anim.getValueFromNanos(playTimeNanos, | |
initialValue, | |
targetValue, | |
initialVelocity) | |
} | |
override fun getVelocityFromNanos( | |
playTimeNanos: Long, | |
initialValue: V, | |
targetValue: V, | |
initialVelocity: V, | |
): V { | |
return anim.getVelocityFromNanos(playTimeNanos, | |
initialValue, | |
targetValue, | |
initialVelocity) | |
} | |
override val delayMillis: Int | |
get() = this@SinWaveAnimationSpec.delay | |
override val durationMillis: Int | |
get() = this@SinWaveAnimationSpec.durationMillis | |
} | |
override fun equals(other: Any?): Boolean = | |
if (other is SinWaveAnimationSpec) { | |
other.durationMillis == this.durationMillis && | |
other.delay == this.delay && | |
other.easing == this.easing | |
} else { | |
false | |
} | |
override fun hashCode(): Int { | |
return (durationMillis * 31 + easing.hashCode()) * 31 + delay | |
} | |
} | |
class SinWaveSpec( | |
val duration: Int = AnimationConstants.DefaultDurationMillis, | |
val delay: Int = 0, | |
private val easing: Easing = FastOutSlowInEasing, | |
private val multiplier: Int, | |
) : FloatAnimationSpec { | |
override fun getValueFromNanos( | |
playTimeNanos: Long, | |
initialValue: Float, | |
targetValue: Float, | |
initialVelocity: Float, | |
): Float { | |
val playTimeMillis = playTimeNanos / 1_000_000L | |
val clampedPlayTime = clampPlayTime(playTimeMillis) | |
val rawFraction = if (duration == 0) 1f else clampedPlayTime / duration.toFloat() | |
val fraction = easing.transform(rawFraction.coerceIn(0f, 1f)) | |
return initialValue + multiplier * (sin(fraction * 2 * Math.PI).toFloat()) | |
} | |
private fun clampPlayTime(playTime: Long): Long { | |
return (playTime - delay).coerceIn(0, duration.toLong()) | |
} | |
override fun getDurationNanos( | |
initialValue: Float, | |
targetValue: Float, | |
initialVelocity: Float, | |
): Long { | |
return (delay + duration) * 1_000_000L | |
} | |
override fun getVelocityFromNanos( | |
playTimeNanos: Long, | |
initialValue: Float, | |
targetValue: Float, | |
initialVelocity: Float, | |
): Float { | |
return 0f | |
} | |
} | |
val SineEasing = Easing { fraction -> sin(fraction * 2 * Math.PI / 4).toFloat() } | |
val InverseCosineEasing = Easing { fraction -> 1 - cos(fraction * 2 * Math.PI / 4).toFloat() } | |
fun Path.heartPath(size: Size): Path { | |
//the logic is taken from StackOverFlow [answer](https://stackoverflow.com/a/41251829/5348665)and converted into extension function | |
val width: Float = size.width | |
val height: Float = size.height | |
moveTo(width / 2, height / 5) | |
cubicTo( | |
5 * width / 14, 0f, | |
0f, height / 15, | |
width / 28, 2 * height / 5 | |
) | |
cubicTo( | |
width / 14, 2 * height / 3, | |
3 * width / 7, 5 * height / 6, | |
width / 2, height | |
) | |
cubicTo( | |
4 * width / 7, 5 * height / 6, | |
13 * width / 14, 2 * height / 3, | |
27 * width / 28, 2 * height / 5 | |
) | |
cubicTo( | |
width, height / 15, | |
9 * width / 14, 0f, | |
width / 2, height / 5 | |
) | |
return this | |
} | |
fun <T> List<T>.safeGet(index: Int?): T? { | |
return if (index != null && index >= 0 && index <= lastIndex) { | |
this[index] | |
} else { | |
null | |
} | |
} | |
fun <T> MutableList<T>.safeSet(index: Int?, update: (value: T) -> T): Boolean { | |
return if (index != null && index >= 0 && index <= lastIndex) { | |
this[index] = update(this[index]) | |
true | |
} else { | |
false | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment