Javascript 在特定时间段内递增端点的计数器

Javascript 在特定时间段内递增端点的计数器,javascript,progress-bar,counter,increment,duration,Javascript,Progress Bar,Counter,Increment,Duration,我正在递增一个计数器,从0开始,直到指定的端点,并在特定的持续时间内递增 函数在持续时间内被无限次调用,以执行计数器的递增 目标是在持续时间的精确末尾将计数器递增到端点 未知的是根据端点和持续时间增加计数器的数值 我的问题是,如何仅使用端点和持续时间作为已知变量来确定递增计数器的数量? 下面是一个代码示例来说明: let duration = 2000; // two seconds let endpoint = 1239; let counter = 0; let numberToIncre

我正在递增一个计数器,从0开始,直到指定的端点,并在特定的持续时间内递增

函数在持续时间内被无限次调用,以执行计数器的递增

目标是在持续时间的精确末尾将计数器递增到端点

未知的是根据端点和持续时间增加计数器的数值

我的问题是,如何仅使用端点和持续时间作为已知变量来确定递增计数器的数量?

下面是一个代码示例来说明:

let duration = 2000; // two seconds
let endpoint = 1239; 
let counter = 0;
let numberToIncrementBy = ''; // this is the unknown

function myFunc() {
    if (counter >= endpoint) {
        // reached the endpoint
        return counter;
    }

    counter += numberToIncrementBy;
    return counter;
}
更新:我在下面这个问题的原因后面添加了更多细节:

我正在使用创建一个动画进度条。要使用它,可以使用
ProgressBar.ShapeName()
创建一个新的Shape对象,并将容器元素作为其第一个参数传递给它。还可以向其传递一个选项对象,从中可以定义持续时间属性

duration = 2000; // duration variable from above
let circle = new ProgressBar.Circle('#the-container', { duration: duration });
创建形状对象后,可以对其调用animate方法,并传入一个
progress
变量(从0到1的数字),以指示动画应停止的位置

circle.animate(0.8); // 80% of progress bar
我为“解决”我的问题所做的是创建一个调用ProgressBars
animate
函数的函数,同时调用一个自定义函数,该函数在动画持续时间内将计数器递增到某个端点,这仍然是一项正在进行的工作

let invokeAnimation = function() {
    let progress = 1400; // arbitary number
    let endpoint = 2100; // also arbitrary but must be larger than progress variable

    // manufacture a progress variable to pass to circle.animate() to determine - between 0 and 1 - where the animation should stop
    let progressEnd = (progress / endpoint).toFixed(2); // 0.67 

    /* set up a function using setInterval to rapidly call a function */
    let counter = 0;

    // NOTE: this variable is critical in ensuring that the counter reaches the progress amount in the time it takes for the animation to complete
    let incrementValue = Math.round(progress / duration * 100); // multiply by 100 and use math round to get a whole number

    let outputStr = " of " + endpoint; // will be combined with progress/counter and output as a string alongside the progress bar in the UI
    let intId = setInterval(frame, 50); // declare a handle to the setInterval function to be able to later CLEAR the interval when no longer needed

    function frame() {
        // the counter has reached its target
        if (counter >= progress) {
            // clear setInterval
            clearInterval(intId);

            // Output text
            // NOTE: circle.setText() is a defined by the ProgressBarJS API and sets the output text of the Shape object
            circle.setText(progress + outputStr );
            return;
        } else {
            circle.setText(counter + outputStr);
            counter += incrementValue;
        }
    }
此代码的作用是可以定义
进度
端点
值,并且在设置的
持续时间
内,计数器将递增至
进度
的值。这将创建与图形进度表或进度条同步的动态文本输出

感谢@cybersam和@NolanWalker试图回答我上面错误的问题。事实上,@NolanWalker建议使用setTimeout,加上在W3School的使用站点上发现的这个例子激发了我的研究结果

同样请注意,上面的代码并没有考虑到函数调用(在我的原始帖子中解释过),函数调用的次数是无限的。此函数是用于创建动画的
circle.animate()
方法的结果

最后,
setInterval
函数将帧速率作为第二个参数。在上面的代码中,我相当随意地将其设置为
50
。我的代码没有在结论中考虑到
帧速率
,我认为这是一个可以改进的方面(但我对我的代码的结果很满意,而且很懒,我现在就把它放在一边!)


干杯

您可以研究使用setTimeout函数,或者为此使用可观察的

Observable.interval(5000)
    .takeWhile(() => !condition)
    .subscribe(i => { 
        // will check every 5 seconds until condition is met
        // executable code
        // set condition to exit 
    })

setTimeout(() => {
  // executable code
  // stops in 5 seconds
}, 5000);

从理论上讲,由于您可以调用增量函数任意次数,因此除非增量不是固定数字,否则无法满足您的要求。例如,“增量”可以始终为0——除非达到
持续时间
,此时它将只是
端点
。(本质上,“增量”直到最后才实际增加计数器。)

getInc0Func
函数返回一个递增函数,该函数在达到
持续时间之前始终返回0:

function getInc0Func(duration, endpoint) {

  let end = Date.now() + duration;

  return function() {
    if (Date.now() >= end) {
      return endpoint;
    }
    return 0;
  }
}
然而,实际上,您可能调用递增函数的次数是“合理的”(例如,小于10^16次)。在这种情况下,可以使用而不是0,这样每个计数器值都将不同:

function getIncFunc(duration, endpoint) {

  let end = Date.now() + duration;
  let counter = 0;

  return function() {
    if (Date.now() >= end) {
      return endpoint;
    }
    return (counter += Number.EPSILON);
  }
}