Search code examples
javascriptcsshtml5-canvaseasingeasing-functions

Can't figure out how to properly use easing function


I really need help to figure out on how to use these easing functions I found on this helpful website: https://spicyyoghurt.com/tools/easing-functions

I know what the values that the function needs means, I created a function in one of my classes that helps me get the current time (t) to pass it to the function afterwards:

getEaseTimeVar()
{
    var timeStamp = performance.now();
    this.#secondsPassed = (timeStamp - this.#oldTimeStamp) / 1000;
    this.#oldTimeStamp = timeStamp;

    return timeStamp;
}

(EXPLANATION) This function works, but only if it is called at the beginning of the code execution. For example, if I want to fade something in (value from 0 to 1) using a linear easing function and call it at the beginning of code execution, it would increase and even go beyond 1, which is fine, that's normal. However, if I want to do the same thing, but I want it to start say 5 seconds after code execution, it will not start at 0, but jump to a larger value.

(PROBLEM) This is because I think I am not getting the time at which the animation starts, but from the start of all code execution, and I am struggling to understand how to do this while still maintaining a simple function to use the easing animation.

Thank you in advance for your help.


Solution

  • Animation start time

    You need to keep track of the animation start time.

    Then use the difference between current time from start time (animTime).

    Only animate while the animTime is between 0 and animation duration.

    Example

    // From https://spicyyoghurt.com/tools/easing-functions
    const easeLinear = (t, b, c, d) => c * t / d + b;
    const easeInOutQuad = (t, b, c, d) => (t /= d * 0.5) < 1 ? c * 0.5 * t * t + b : -c * 0.5 * ((t - 1) * (t - 3) - 1) + b;
    
    var animating = false;
    var startTime;
    const animDuration = 2000; // ms
    const ctx = canvas.getContext("2d");
    
    canvas.addEventListener("click",() => {
        startTime = performance.now(); 
        !animating && requestAnimationFrame(mainLoop); 
    });
    
    function mainLoop(time) {
         ctx.clearRect(0, 0, canvas.width, canvas.height);
         if (startTime) {
             var animTime = time - startTime;
             // or var animTime = performance.now() - startTime
    
             const x = easeLinear(animTime, -20, canvas.width + 40, animDuration);
             const y = easeInOutQuad(animTime, 20, canvas.height - 40, animDuration);         
             ctx.beginPath();
             ctx.arc(x, y, 20, 0, Math.PI * 2);
             ctx.fill();
             if (animTime < animDuration) {
                 requestAnimationFrame(mainLoop);
                 animating = true;
             } else {
                 animating = false;
             }
         }
    
    }
    canvas { border: 1px solid black; }
    Click canvas to start / restart animation.<br>
    <canvas id="canvas" width="500" height="200"></canvas>