Javascript 如何在循环中的两个值X,Y之间来回移动?

Javascript 如何在循环中的两个值X,Y之间来回移动?,javascript,lerp,Javascript,Lerp,使用setInterval或RequestAnimationFrame,我希望从X和Y之间的lerping中获取进度值。假设X为0,Y为1,我希望开始时为0,一半时为0.5,完成时为1 我希望这在给定的时间范围内发生,比如说5秒。这意味着,当setInterval/RequestAnimationFrame达到2.5秒时,将出现半值0.5 最后,我希望它是乒乓球,所以当它达到5秒时,值是递减的,而不是递增的,比如0.9、0.8、0.7等等,然后从0、0.1、0.2开始 以下是我目前的代码: /*

使用setInterval或RequestAnimationFrame,我希望从X和Y之间的lerping中获取进度值。假设X为0,Y为1,我希望开始时为0,一半时为0.5,完成时为1

我希望这在给定的时间范围内发生,比如说5秒。这意味着,当setInterval/RequestAnimationFrame达到2.5秒时,将出现半值0.5

最后,我希望它是乒乓球,所以当它达到5秒时,值是递减的,而不是递增的,比如0.9、0.8、0.7等等,然后从0、0.1、0.2开始

以下是我目前的代码:

/*
function lerp(start, end, time) {
    return start * (1.0 - time) + end * time;
}
*/
function lerp (start, end, amt){
  return (1-amt)*start+amt*end;
}

function repeat(t, len) {
  console.log('t: ' + t + ', len: ' + len);
    return t - Math.floor(t / len) * len;
}

function pingPong(t, len) {
    t = repeat(t, len * 2);
    return len - Math.abs(t-len);
}

var transitionDuration = 1;
var startTime = Date.now()/1000;
var startPos = 0;
var endPos = 1;

setInterval(function () {
    var currentTime = Date.now()/1000;
  console.log('currentTime:', currentTime);
    var adjustedTime = pingPong(currentTime-startTime, transitionDuration);
    var x = lerp(startPos, endPos, adjustedTime);

    console.log(Math.abs(x.toFixed(2)));

}, 100);

我该怎么做呢?

线性插值的基本公式如下

InterpolatedValue = X*t + Y*(1-t)
其中,
X
Y
是要在之间插值的值,
t
是介于
0
1
之间的参数,用于确定插值程度<代码>0产生
X
1
产生
Y
。此外,您希望有一些周期运动,周期长度为
5
,交替插值方向;这可以通过以下方式实现。如果
t
是一个随时间增长的非负数,则计算

t' = t - t / 10
要删除以前发生的所有期间,请执行以下操作:

t'' = t'     : t' in [0,5)
      5 - t' : t' in [5,10)
然后设置

t''' = t' / 5
将参数规格化为
[0,1]
,并从一开始就使用基本插值公式


请注意,会收集线性插值和各种其他方法。

根据您的描述,在任何给定帧上都有6个状态:

  • 当前lerp的开始时间
  • Lerp时间跨度
  • 电流方向
  • 当前时间
  • 起始值
  • 终值
  • 根据这些,您可以计算所需的进度值,例如:

    function progressValue(startTime, lerpSpanSeconds, dir, 
                           currentTime X, Y, dir, currentTime) {
        // lerp
        return 0.42;
    }
    
    对于requestAnimationFrame。也就是说,函数必须知道它所需要的一切,除了在运行时可以获取的信息。在这里,当它运行时,只需要获取当前时间,然后从那里计算出其余的时间

    function animableThing() {
        var startTime = 7;
        var lerpSpanSeconds = 3;
        var dir = +1;
        var X = 0;
        var Y = 1;
        var currentTime = GetCurrentUnicornTime();
        var thingToAnimate = document.getElementById('myAnimableElement');
    
        var progress = progressValue(startTime, lerpSpanSeconds, dir, 
              currentTime, X, Y, dir, currentTime);
        // reverse when we hit the end
        if(progress > Y) {
            dir *= -1;
            startTime = currentTime;
            progress = Y;
        }
    
        DrawAnimationThing(thingToAnimate, progress);
    
        // continue the animation
        window.requestAnimationFrame(animableThing);
    }
    
    但是有一个问题;如果您希望能够使用脚本中的值或屏幕上的输入或屏幕上元素的最新信息来设置动画,则需要能够在有新值时使
    animableThing
    回调刷新。看哪,母亲:

    function MotherOfAnimableThings(startTime, lerpSpanSeconds, dir, X, Y, 
       thingToAnimate)
    {
        // Passed in variables have scope outside the animableThing, these
        // will be private to the animableThing function.
        // Consider defaulting or validation here
    
        // Construct a new function freshly each time the Mother is called,
        // and return it to the caller. Note that we assign a variable here
        // so that we can re-call RequestAnimationFrame to continue the loop
        var callback = (function() {
            var currentTime = GetCurrentUnicornTime();
            var progress = progressValue(startTime, lerpSpanSeconds, dir, 
                  currentTime, X, Y, dir, currentTime);
            // reverse when we hit the end
            if(progress > Y) {
                dir *= -1;
                startTime = currentTime;
                progress = Y;
            }
    
            DrawAnimationThing(thingToAnimate, progress);
    
            window.requestAnimationFrame(callback);
        });
        return callback;
    }
    
    我们可以更进一步,让调用者传入一个progressValue函数来调用,或者实际上是一个回调,这样你就可以获取任何元素,绘制函数和设置函数,制作一个动画,但是这是一个合理的起点

    在上面,我们只需要调用Mother来创建一个
    animableThing
    函数,并使用该函数调用RequestAnimationFrame。从那时起,它在内部调用RequestAnimationFrame以继续循环

    现在,完成后,您将希望使其停止,因此在回调中添加一个可以检查的变量,以便执行以下操作

    var animableThing = MotherOfAnimableThings(...);
    window.requestAnimationFrame(animableThing);
    // ... later
    animableThing.stop = true; // it should stop on the next frame
    

    你试过什么吗?你被困在哪里?详细说明@AramilRey的问题;你试过什么?你做了什么研究?你能提供一些片段来证明你自己已经尝试过解决这个问题吗?(一个简单的谷歌搜索将为你提供解决这个问题所需的知识。)你不应该依赖SO社区为你做工作。我一直在玩它,但我不知道如何让它在0到400之间反弹。我在这里创建了一个代码笔--请您帮助我使这个“t”在0和1之间反弹。这里有一个要点-