如何在requestAnimationframe循环中的2个点之间进行插值

时间:2017-10-13 04:20:11

标签: javascript animation interpolation requestanimationframe

如果有的话,我很乐意带一个图书馆吗?或者对我的psuedocode api的任何其他建议。

问题:

如何编写一个带有4个参数interpolate(start, end, time, ease)的函数,并在一段时间内轻松插入开始到结束的数字?

问题:

这感觉特别难,因为我不知道如何在请求动画帧中控制时间或轻松。其次,我不知道如何编写贝塞尔曲线处理程序。最后,如果需要进行优化。

  interpolate(start:number, end:number, time:number, ease) {
    // easing
    return value;
  }

  function _draw() {
    currentValue = interpolate(0, 10, 0.7, 'cubic-bezier(.62,.28,.23,.99)');
    if(currentValue !== lastValue) {
      console.log(currentValue)
    }
    requestAnimationFrame(_draw);
  }

所以最后currentValue会在它的最终刻度中记录10。

1 个答案:

答案 0 :(得分:2)

我建议使用Penner Equations进行通用缓和。这些函数可以在github上找到库:  tween-functions

一个简单的演示,展示如何在每个帧上计算值:



const Easings = [
  function easeInQuad(t, b, c, d) {
    return c * (t /= d) * t + b;
  },
  function easeOutBounce(t, b, c, d) {
    if ((t /= d) < (1 / 2.75)) {
      return c * (7.5625 * t * t) + b;
    } else if (t < (2 / 2.75)) {
      return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
    } else if (t < (2.5 / 2.75)) {
      return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
    } else {
      return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
    }
  },
  function easeInOutElastic(t, b, c, d) {
    // jshint eqeqeq: false, -W041: true
    var s = 1.70158;
    var p = 0;
    var a = c;
    if (t == 0) return b;
    if ((t /= d / 2) == 2) return b + c;
    if (!p) p = d * (0.3 * 1.5);
    if (a < Math.abs(c)) {
      a = c;
      s = p / 4;
    } else s = p / (2 * Math.PI) * Math.asin(c / a);
    if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
  },
];
const duration = 2000;
const div = document.querySelector('div');

let start = Date.now();
let from = 0;
let to = 300;
let fnCounter = 0;
let fn = Easings[fnCounter];


function tick() {
  let now = Date.now();
  let elapsed = now - start;
  let val = fn(elapsed, from, to - from, duration);
  div.style.transform = `translateX(${val}px)`;
  if (elapsed >= duration) {
    start = now;
    let x = from;
    from = to;
    to = x;
    fn = Easings[++fnCounter % Easings.length]
    setTimeout(tick, 300);
    return;
  }
  requestAnimationFrame(tick);
}

requestAnimationFrame(tick);
&#13;
div {
  position: absolute;
  top: 0px;
  left: 0;
  width: 100px;
  height: 100px;
  background: orange;
}
&#13;
<div></div>
&#13;
&#13;
&#13;

对于自定义贝塞尔曲线,我建议使用此库:bezier-easing。这里的计算是相同的:在每个刻度线上,您可以获得经过的时间并计算持续时间的百分比,现在每个帧上都有01的刻度值。