遅延感知しながら移動する。


書いてみてから、今!気づく!
時間から移動位置を決めるのではなく、移動量を得て移動する!
ですね。

アホな考えだった。休むに似たり。

なんだよ〜俺!
あぁ〜。


終了していなかったのでコードを修正。

<!DOCTYPE html>
<title>遅延時間を考えて移動する</title>
<meta charset="UTF-8">
<style>
li {
  position: relative;
  left : 0;
}
</style>

<ol id="invader">
  <li>
    ease:
    <img class ="invader"
             alt="ease"
             src="data:image/gif;base64,
                  R0lGODlhMAAYAIAAAP8ntf///yH5BAEAAAEALAAAAAAwABgAAAJijI95wO2sopzqWUCzXtft
                  34Vi8yHjeZUcymJgC3tZTLtUHWth9fDp3PGREjvgz9QjBo04lK7JekJPKkMReaxiLcKkdutd
                  cb+BMdgmhlTNabQ1/JKdu24VW3L/5unkOVNNUQAAOw==">
  <li>
    liner:
    <img class ="invader"
             alt="linear"
             src="data:image/gif;base64,
                  R0lGODlhMAAYAIAAAP8ntf///yH5BAEAAAEALAAAAAAwABgAAAJijI95wO2sopzqWUCzXtft
                  34Vi8yHjeZUcymJgC3tZTLtUHWth9fDp3PGREjvgz9QjBo04lK7JekJPKkMReaxiLcKkdutd
                  cb+BMdgmhlTNabQ1/JKdu24VW3L/5unkOVNNUQAAOw==">
  <li>
    ease-in:
    <img class ="invader"
             alt="ease-in"
             src="data:image/gif;base64,
                  R0lGODlhMAAYAIAAAP8ntf///yH5BAEAAAEALAAAAAAwABgAAAJijI95wO2sopzqWUCzXtft
                  34Vi8yHjeZUcymJgC3tZTLtUHWth9fDp3PGREjvgz9QjBo04lK7JekJPKkMReaxiLcKkdutd
                  cb+BMdgmhlTNabQ1/JKdu24VW3L/5unkOVNNUQAAOw==">
  <li>
    ease-out:
    <img class ="invader"
             alt="ease-out"
             src="data:image/gif;base64,
                  R0lGODlhMAAYAIAAAP8ntf///yH5BAEAAAEALAAAAAAwABgAAAJijI95wO2sopzqWUCzXtft
                  34Vi8yHjeZUcymJgC3tZTLtUHWth9fDp3PGREjvgz9QjBo04lK7JekJPKkMReaxiLcKkdutd
                  cb+BMdgmhlTNabQ1/JKdu24VW3L/5unkOVNNUQAAOw==">
</ol>


<script>

// requestAnimationFrame
if ('undefined' === typeof this.requestAnimationFrame) {
  this.requestAnimationFrame =
    this.requestAnimationFrame ||
    this.webkitRequestAnimationFrame||
    this.mozRequestAnimationFrame   ||
    this.oRequestAnimationFrame     ||
    this.msRequestAnimationFrame    ||
    function (callback, that) {
      var tmpFunc = function () {
        var timestamp = +(new Date); //(new Date).getTime ();
        callback (timestamp); //callback.call (that, timestamp);
      };
      win.setTimeout (tmpFunc, Math.floor (1000 / 60));
    };
}
  

(function () {
  //__________

  // ベジェ曲線を更に高速化したもの (始点:0・終点限定:1)戻り値は[x,y]
  //cubic-bezier
  function cubic_bezier (x1, y1, x2, y2) {
    if (x1 < 0 || 1 < x1 || x2 < 0 || 1 < x2)
      throw new Error ('範囲外');
    
    return function (t) {
      
      var a = (1 - t);
      var b = 3 * a * t;

      var A = b * a;
      var B = b * t;
      var C = t * t * t;

      return [
        A * x1 + B * x2 + C,
        A * y1 + B * y2 + C
      ];
    };
  }
  
  
  // 呼び出す関数を1つにまとめる。
  function cbFuncCollector (/* cbFunc0, cbFunc1, ..*/) {
    var cbFuncStock = Array.prototype.slice.call (arguments, 0);

    return function (i) {
      for (var n = 0, func; func = cbFuncStock [n++]; ) {
        func (i);
      }
    };
  }
  

  //_________________
  // アニメーションの遅延を感知しながら補う
  function CompensateInterval (cbFunc, duration, timingFunc, delay, maxCompensate, interval, through) {
    this.cbFunc         = cbFunc; // コールバック
    this.duration       = duration; // 作動時間
    this.timingFunc     = timingFunc; // ベジェ曲線の関数
    this.delay          = delay;  // ms 秒後に開始
    this.maxCompensate  = maxCompensate; //最大補間回数
    this.interval       = interval; // 間隔
    this.through        = through; // 遅延が発生したならコールバックを呼ばない (default: true)
    
    this.step           = 1 / (duration / interval);
    this.count          = null;
    this.startTime      = null;
    this.timeCount      = null; //ベジェ曲線に渡す引数(time)
  }
  
  
  function loop (timeStamp) {
    var max = this.maxCompensate;
    var delay = (timeStamp - this.startTime) - this.interval * this.count;
    var endF = false;
    var r;

    do {
      if (max === this.maxCompensate || ! this.through) { //遅延中&スルーするなら何もしない
        r = this.timingFunc (this.timeCount);
        this.cbFunc (r[0], r[1], this.timeCount);
      }

      if (endF || this.timeCount ===1)
        return;

      this.timeCount += this.step;

      if (1 < this.timeCount) { //確実に1にして終わらせる
        this.timeCount = 1;
        endF = true;
      }

      this.count += 1;

      if (0 === max++) //打ち切り
        break;

      delay -= this.interval;
    } while (0 < delay); // 遅延があれば

    return requestAnimationFrame (loop.bind (this));
  }
  
  
  function CompensateInterval_init () {
    this.count = 0;
    this.timeCount = 0;
    this.startTime = (new Date).getTime ();
    loop.call (this);
  }
  
  
  function CompensateInterval_start () {
    if (this.delay)
      setTimeout (CompensateInterval_init.bind (this), this.delay);
    else
      CompensateInterval_init.call (this);
  }
  
  
  function CompensateInterval_create (cbFunc, duration, timingFunc, delay, maxCompensate, interval, through) {
    if (3 > arguments.length)
      throw new Error;
    
    switch (typeof timingFunc) {
    case 'function' :
      break;
    
    case 'string' :
      switch (timingFunc) {
      
      case 'ease' :
        timingFunc = cubic_bezier (0.25, 0.1, 0.25, 1.0);
        break;
      
      case 'linear' :
        timingFunc = cubic_bezier (0.0, 0.0, 1.0, 1.0);
        break;
        
      case 'ease-in' :
        timingFunc = cubic_bezier (0.42, 0, 1.0, 1.0);
        break;
        
      case 'ease-out' :
        timingFunc = cubic_bezier (0, 0, 0.58, 1.0);
        break;
      
      default :
        throw new Error ('Not know name');
      }
      break;
    
    default :
      throw new Error ('Syntax error');
    }
    
    return new CompensateInterval (cbFunc, duration, timingFunc, delay || 0, maxCompensate || 3, interval || 1000 / 60, through || true);
  }
  
  
  CompensateInterval.prototype.start = CompensateInterval_start;
  CompensateInterval.create          = CompensateInterval_create;
  
  this.CompensateInterval = CompensateInterval;
  //_________________
  
  
  this.cubic_bezier = cubic_bezier;
  this.cbFuncCollect = cbFuncCollector;
}) ();


//############################################

// 右に移動させる
var move =
  (function (e) {
    var style = e.style;
    var max = 800;

    return function (x, y, t) {
      style.left = Math.floor (x * max) + 'px';
    };
  });


Array.prototype.forEach.call (
  document.querySelectorAll ('#invader > li'),
    function (e, i) {
      (CompensateInterval.create (move(e), 3000, this[i]).start ());
    },
    ['ease', 'linear', 'ease-in', 'ease-out' ])

</script>