Parse

File Parse iter/lerp.js

This tree is parsed live from the source file.

Classes

  • {{ item.name }}

    • {{ key }}

Not Classes

{{ getTree() }}

Comments

{{ getTreeComments() }}

Source

            /* A LerpValue provides a number between two numbers. The stepping function can be linear
or another easing.

    v = Value(1, 100)
    v.get(.5) -> ~50

    v = Value(1, 100, cubicSmooth)
    v.get(.7) -> ~90
    v.get(.9) -> ~99

Stepping over time may need a tick step function

    v = Value(1, 100)
    v.deltaFrom = stage.clock.tick
    v.step(delta=14ms)
    // somehow flag 1sec of 60fps?
    v.get()
    v.get()
    v.get()

Divisor Values accept an A, B and a splitting V

    Value(0, 1, 100)
    v.get(.5) -> .05

---

    v=Value(100, 600, quadEaseInOut)

===

This could be used for time, by providing to _dates_ and calulating the
distance between an expected time, and a smoothed time.

    // 2 seconds

    v = Value(+Date, +Date+2000)
    v.step(.7) // should be at seconds location.

    v = Value(+Date, +Date+2000, quinticEaseInout)
    v.step(.7) // will be ahead of the first value by X seconds

---
    const secondsEasing = function(v) {
        // a easing function to flag _time over seconds_ from
        // a relative start time.
    }

    let deltaFrom = 0
    let fps = 60
    let delta = 14 // ms - for one delta over 1000ms (I think.)
    // 1 to 100 over 4 seconds.
    v = Value(1, 100, seconds(4, deltaFrom, fps))
    v.step(delta)
*/


class Value {

    constructor(a=0, b=1, easing=undefined, doneStop=false) {
        this.a = a
        this.fix = 5
        this.b = b
        this.step = .005
        this.done = false
        this.doneStop = doneStop

        this.setEasing(easing)
    }

    setEasing(easing){
        let linear = v=>v;
        // let linear = v=>Number(v.toFixed(this.fix));
        this.easing = easing == undefined? linear: easing
    }

    width(a=this.a, b=this.b){
        return b - a
    }

    t(v, a=this.a, b=this.b) {
        return this.width(a, b) * v
    }

    get(step=this.step, easing=this.easing, a=this.a, b=this.b){
        /* a smoothing function */
        // console.log('Value In', step)

        let mutator = this.mutate(step, easing)

        // console.log('Mutated', mutator)
        let done = step >= (1 - .00001)
        if(done && this.doneStop) { mutator = 1 }
        let raw = this.t(mutator, a, b)
        // console.log('Computed', raw)
        let res = a + raw

        if(done == true) {
            this.emitDoneEvent(res, raw, mutator, step)
        }

        // console.log('Result', res)
        return res
    }

    pluck(a=this.a, b=this.b,  step=this.step, easing=this.easing) {
        return this.get(step, easing, a, b)
    }

    mutate(value, easing) {
        let easingUnit= (easing == undefined? this.easing: easing)
        try{
            return easingUnit(value)
        }catch {
            debugger;
        }
    }

    emitDoneEvent(value, preValue, mutator, step) {
        if(this.done == false){
            this.doneHandler(value, preValue, mutator, step)
        }
        this.done = true
    }

    doneHandler(value, preValue, mutator, step) {
        // console.log('done', value, preValue)
    }

    split(count=1) {
        /* return a list of numbers, split through the count divisor

        v= new Value(100, 600)
        v.split(10)[9] == 600
        v.split(2) == [100, 600]
        */

        let r = []
        let divisor = 1/(count-1);
        for (var i = 0; i < count; i++) {
            let step = i * divisor;

            r.push(this.get(step))
        }
        return r
    }
}



class PointListLerper {

    constructor(pointList) {
        this.parent = pointList
        this.lerpKeys = ['x', 'y', 'radius', 'rotation']
        this.currentTime = 0
        this.seconds = 2
    }

    getCommonValue() {
        if(this.commonValue) {
            return this.commonValue
        };

        let commonValue = this.commonValue = new Value()
        commonValue.doneStop = true
        commonValue.setEasing(this.getCommonEasingFunction())
        return commonValue
    }

    getCommonEasingFunction(){
        /* return an easing function */
        return quarticEaseInOut
    }

    through(a, b, settings) {
        /* Lerp this entire pointlist from _a_ to _b_.
        Settings can be a number or a settings object. */
        let d = {
            /* time taken over the deltatime  currentTime */
            seconds: this.seconds
            /* values on a point to lerp.*/
            , keys: this.lerpKeys
            , currentTime: this.currentTime
            , easing: undefined
            , fps: 60
            , delay: 0
            // , easing:
        }

        Object.assign(d, settings)
        // d.delta = 1 / (d.fps * (d.seconds + d.delay))

        let spl = 1 / (d.fps * (d.seconds + d.delay)) // d.delta
            , lerpKeys = d.keys
            , commonVal = this.getCommonValue()
            , pa = a
            , pb = b
            /* a percent of 0 to 1.*/
            , currentTime = d.currentTime + spl
            // , currentTime = this.currentTime = d.currentTime + spl
            , easingFunction = d.easing
            ;

        this.currentTime += spl
        // this.currentTime = d.currentTime + spl
        this.parent.forEach((p,i)=> {
            let a = pa[i]
            let b = pb[i]
            let di = d[i]

            if(di !=undefined
                && (di.seconds != undefined
                    || di.delay != undefined)
                && di?.currentTime == undefined
            ) {
                /* precompute*/
                let _seconds = di.seconds == undefined? d.seconds: di.seconds
                let _delay = di.delay == undefined? d.delay: di.delay
                di.currentTime = -(_delay/_seconds)
            }

            /* A custom easing function by index. */
            let ease = di?.easing == undefined? easingFunction: di.easing;
            var ct = di?.currentTime == undefined? currentTime: di.currentTime;
            if(di?.seconds || di?.delay) {
                let _seconds = di.seconds == undefined? d.seconds: di.seconds
                let spl = 1 / (d.fps * _seconds)
                ct = ct + spl
                di.currentTime = ct
            }

            lerpKeys.forEach(k=>{
                /* iterate the target values of the _current_ point.
                Use the common Value to calculate the eased new value.*/
                if (ct < 0) ct=0;
                p[k] = commonVal.pluck(a[k], b[k], ct, ease)
            })

        })



    }
}

Polypoint.head.install(PointListLerper)

Polypoint.head.deferredProp('PointList',
    function lerper() {
        return new PointListLerper(this)
    }
);


copy