Ease Out Factory

Demonstrates the use of an adjustable ease out easing curve based on a sigmoid function.

HTML

<div id="ball"></div>

CSS

body {
  padding: 0;
  margin: 0;
  background: white;
}
#ball {
  position: absolute;
  top: calc(50% - 50px);
  left: calc(25% - 50px);
  width: 100px;
  height: 100px;
  border-radius: 100%;
  background-color: rgba(0,0,0,.8);
}

JavaScript

window.onload = function () {
  var ball = document.getElementById('ball');

  animation({
    obj: ball,
    msec: 1250,
    length: 50,
    easing: easeOutFactory(6),
  });
};

/* Example animation function 
* 
* Interpolate between a start and end position.
*
* obj.left represents a position parameter (e.g. 12.2)
* length is the value obj.left will have at the end of the animation
* msec is the number of milliseconds we want to run the animation for
* easing is a timing function that accepts a number between 0 to 1 
*    and returns the proportion of the interpolation between start and end to move the object to. 
* 
* Returns: void (performs animation as a side effect)
*/
function animation (args) {
  args = args || {};

  var easing = args.easing || function (t) { return t }; // default to linear easing
  var obj = args.obj;

  var style = window.getComputedStyle(obj);

  var start_pos = parseInt(style.left, 10),
      length = args.length || 0,
      msec = args.msec || 1000;

  // performance.now is guaranteed to increase and gives sub-millisecond resolution
  // Date.now is susceptible to system clock changes and gives some number of milliseconds resolution
  var start = window.performance.now();

  function displacement (fraction) {
    var width = parseFloat(style.width.replace("px", ''), 10);
    width /= 2;
    width += "px";

    return "calc(25% - " + width  + " + " +  (fraction * length) + "%)";
  }

  function frame () {
    var now = window.performance.now();
    var t = (now - start) / msec; // normalize to 0..1

    if (t >= 1) { // if animation complete or running over
      obj.style.left = displacement(easing(1)); // ensure the animation terminates in the specified state
      return;
    }

    obj.style.left = displacement(easing(t));

    requestAnimationFrame(frame); // next frame!
  }

  requestAnimationFrame(frame); // you can use setInterval, but this will give a smoother animation
}

function clamp (x, min, max) {
  return...