【问题标题】:How to interpolate between 2 points in a requestAnimationframe loop如何在 requestAnimationframe 循环中的 2 个点之间进行插值
【发布时间】:2017-10-13 04:20:10
【问题描述】:

如果可以的话,我会很乐意为此使用图书馆吗?或对我的 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 会在 0.7 的最后一个刻度中注销 10。

【问题讨论】:

    标签: javascript animation interpolation requestanimationframe


    【解决方案1】:

    我建议使用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);
    div {
      position: absolute;
      top: 0px;
      left: 0;
      width: 100px;
      height: 100px;
      background: orange;
    }
    &lt;div&gt;&lt;/div&gt;

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

    【讨论】:

      猜你喜欢
      • 2016-10-24
      • 2023-04-11
      • 2012-07-14
      • 2020-12-27
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多