All Downloads are FREE. Search and download functionalities are using the official Maven repository.

2v-ease-common.0.8.0-RC3.source-code.EaseCommon.kt Maven / Gradle / Ivy

There is a newer version: 0.8.0-RC5
Show newest version
package io.data2viz.ease

import kotlin.math.*

typealias EaseFun = (Double) -> (Double)

private const val tau = 2 * PI
private const val halfPi = PI / 2
private const val b1 = 4.0 / 11
private const val b2 = 6.0 / 11
private const val b3 = 8.0 / 11
private const val b4 = 3.0 / 4
private const val b5 = 9.0 / 11
private const val b6 = 10.0 / 11
private const val b7 = 15.0 / 16
private const val b8 = 21.0 / 22
private const val b9 = 63.0 / 64
private const val b0 = 1.0 / b1 / b1

class ease {
    companion object {
        val linear: EaseFun = { it }

        val bounceIn: EaseFun   = { 1 - bounceOut(1 - it) }
        val bounceOut: EaseFun  = { t ->
            when {
                t < b1 -> b0 * t * t
                t < b3 -> b0 * (t - b2) * (t - b2) + b4
                t < b6 -> b0 * (t - b5) * (t - b5) + b7
                else ->   b0 * (t - b8) * (t - b8) + b9
            }
        }
        val bounceInOut: EaseFun = {
            (it * 2).let {
                if (it <= 1) 1 - bounceOut(1-it)
                else bounceOut(it - 1) + 1
            } / 2
        }

        val circleIn    : EaseFun = { 1 - sqrt(1 - it * it) }
        val circleOut   : EaseFun = { sqrt(1.0 - (it - 1) * (it - 1)) }
        val circleInOut : EaseFun = {
            (it * 2).let {
                if (it <= 1) 1 - sqrt(1 - it * it)
                else sqrt(1.0 - (it - 2) * (it - 2)) + 1
            } / 2
        }

        val cubicIn    : EaseFun = { it * it * it }
        val cubicOut   : EaseFun = { (it - 1) * (it - 1) * (it - 1) + 1 }
        val cubicInOut : EaseFun = {
            (it * 2).let {
                if (it <= 1) it * it * it
                else (it - 2) * (it - 2) * (it - 2) + 2
            } / 2
        }

        val expIn: EaseFun = { 2.0.pow(10.0 * it - 10) }
        val expOut: EaseFun = { 1 - 2.0.pow(-10 * it) }
        val expInOut: EaseFun =
            { (it * 2).let { if (it <= 1) 2.0.pow(10.0 * it - 10) else 2 - 2.0.pow(10 - 10 * it) } / 2 }

        val quadIn: EaseFun = { it * it }
        val quadOut: EaseFun = { it * (2 - it) }
        val quadInOut: EaseFun = { (it * 2).let { 
            if (it <= 1) it * it 
            else (it - 1) * (3 - it) + 1 } / 2 }


        val sinIn: EaseFun      = { 1 - cos(it * halfPi) }
        val sinOut: EaseFun     = { sin(it * halfPi) }
        val sinInOut: EaseFun   = { (1 - cos(PI * it)) / 2 }
        
        //configurable easing functions (implemented as class with invoke operator)
        val backIn      = BackIn()
        val backOut     = BackOut()
        val backInOut   = BackInOut()

        val elasticIn   = ElasticIn()
        val elasticOut  = ElasticOut()
        val elasticInOut = ElasticInOut()

        val polyIn      = PolyIn()
        val polyOut     = PolyOut()
        val polyInOut   = PolyInOut()
    }
}



class ElasticIn(
    private val amplitude: Double = 1.0,
    private val period: Double = 0.3
) {

    private val a = amplitude.coerceAtLeast(1.0)
    private val p = period / tau
    private val s = asin(1 / a) * p
    
    fun amplitude(amplitude: Double) = ElasticIn(amplitude, period)
    fun period(period: Double) = ElasticIn(amplitude, period)
    
    operator fun invoke(t: Double): Double = a * 2.0.pow(10 * (t-1)) * sin((s -t + 1)/p)
}

class ElasticOut(
    private val amplitude: Double = 1.0,
    private val period: Double = 0.3
) {
    private val a = amplitude.coerceAtLeast(1.0)
    private val p = period / tau
    private val s = asin(1 / a) * p

    fun amplitude(amplitude: Double) = ElasticOut(amplitude, period)
    fun period(period: Double) = ElasticOut(amplitude, period)

    operator fun invoke(t: Double) = 1 - a * 2.0.pow(-10 * t) * sin((t + s) / p)
}

class ElasticInOut(
    private val amplitude: Double = 1.0,
    private val period: Double = 0.3
) {
    private val a = amplitude.coerceAtLeast(1.0)
    private val p = period / tau
    private val s = asin(1 / a) * p

    fun amplitude(amplitude: Double) = ElasticInOut(amplitude, period)
    fun period(period: Double) = ElasticInOut(amplitude, period)

    operator fun invoke(t: Double) = (t * 2 - 1).let {
        if (it < 0) a * 2.0.pow(10 * it) * sin((s - it) / p)
        else 2.0 - a * 2.0.pow(-10 * it) * sin((s + it) / p)
    } / 2
}

class BackIn(private val overshoot: Double = 1.70158) {
    fun overshoot(overshoot: Double) = BackIn(overshoot)
    operator fun invoke(t: Double): Double = t * t * ((overshoot + 1) * t - overshoot)
}
class BackOut(private val overshoot: Double = 1.70158) {
    fun overshoot(overshoot: Double) = BackOut(overshoot)
    operator fun invoke(t: Double): Double = (t-1) * (t-1) * ((overshoot +1) * (t-1) + overshoot) + 1
}

class BackInOut(private val overshoot: Double = 1.70158) {
    fun overshoot(overshoot: Double) = BackInOut(overshoot)
    operator fun invoke(t: Double) = (t * 2).let {
        if (it < 1) it * it * ((overshoot+1) * it - overshoot)
        else (it -2) * (it-2) * ((overshoot +1) * (it-2) + overshoot) + 2
    } / 2
}

class PolyIn(private val exponent: Double = 3.0) {
    fun exponent(exponent: Double) = PolyIn(exponent)
    operator fun invoke(t: Double): Double = t.pow(exponent)
}

class PolyOut(private val exponent: Double = 3.0) {
    fun exponent(exponent: Double) = PolyOut(exponent)
    operator fun invoke(t: Double) = 1 - (1 - t).pow(exponent)
}

class PolyInOut(private val exponent: Double = 3.0) {
    fun exponent(exponent: Double) = PolyInOut(exponent)
    operator fun invoke(t: Double) = (t * 2).let {
        if (it <= 1)
            it.pow(exponent)
        else
            2 - (2 - it).pow(exponent)
    } / 2
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy