Search code examples
javascriptanimationcanvaseasing

Maths and Easing For Javascript/Canvas Preload Animation


I'm building an image preload animation, that is a circle/pie that gets drawn. Each 'slice' is totalImages / imagesLoaded. So if there are four images and 2 have loaded, it should draw to 180 over time.

I'm using requestAnimFrame, which is working great, and I've got a deltaTime setup to restrict animation to time, however I'm having trouble getting my head around the maths. The closest I can get is that it animates and eases to near where it's supposed to be, but then the value increments become smaller and smaller. Essentially it will never reach the completed value. (90 degrees, if one image has loaded, as an example).

var totalImages = 4;
var imagesLoaded = 1;
var currentArc = 0;

function drawPie(){
  var newArc = 360 / totalImages * this.imagesLoaded // Get the value in degrees that we should animate to
  var percentage = (isNaN(currentArc / newArc) || !isFinite(currentArc / newArc)) || (currentArc / newArc) > 1 ? 1 : (currentArc / newArc); // Dividing these two numbers sometimes returned NaN or Infinity/-Infinity, so this is a fallback
  var easeValue = easeInOutExpo(percentage, 0, newArc, 1);

  //This animates continuously (Obviously), because it's just constantly adding to itself:
  currentArc += easedValue * this.time.delta;

  OR

  //This never reaches the full amount, as increments get infinitely smaller
  currentArc += (newArc - easedValue) * this.time.delta;
}

function easeInOutExpo(t, b, c, d){
  return c*((t=t/d-1)*t*t + 1) + b;
}

I feel like I've got all the right elements and values. I'm just putting them together incorrectly.

Any and all help appreciated.


Solution

  • You've got the idea of easing. The reality is that at some point you cap the value.
    If you're up for a little learning, you can brush up on Zeno's paradoxes (the appropriate one here being Achilles and the Tortoise) -- it's really short... The Dichotomy Paradox is the other side of the same coin.

    Basically, you're only ever half-way there, regardless of where "here" or "there" may be, and thus you can never take a "final"-step.
    And when dealing with fractions, such as with easing, that's very true. You can always get smaller.

    So the solution is just to clamp it. Set a minimum amount that you can move in an update (2px or 1px, or 0.5px... or play around).

    The alternative (which ends up being similar, but perhaps a bit jumpier), is to set a threshold distance. To say "As soon as it's within 4px of home, snap to the end", or switch to a linear model, rather than continuing the easing.