如何根据离散步骤插入进度?

时间:2014-12-10 15:26:00

标签: javascript function math interpolation progress

在Web应用程序中,某个任务需要多个连续的ajax调用步骤才能完成。每个需要12-18秒。

我希望向用户提供一个进度指示器,而这个指示器经常会做出很少的步骤。

我的第一个赌注是假设一个线性progress = k * time函数,在每个新响应上自我调整kFiddle emulated响应时间为+ - 4s范围内的随机值。

这种做法似乎是错误的:在一系列快速反应之后反应相对较长的情况下,进展会采取消极措施来赶上真正的步伐。

感觉就像一个函数应该进入“波浪”:开始时更快,在延迟检查点的情况下减慢到接近结束的程度。

完成此类任务的最佳做法是什么?

1 个答案:

答案 0 :(得分:1)

我将专注于您的请求的数学部分:

  

一个函数应该进入“波浪”:开始时速度更快,在延迟检查点的情况下减慢到接近结束的程度

翻译:具有正初始梯度的单调函数(即没有后向步骤)和大x的渐近行为。

考虑atan(theta):对于小x,它的梯度为1,对于大x,渐近接近π/ 2。我们可以对它进行缩放,以便当块在可用长度的某个部分时发生预期的结束 - 也就是说,如果你期望它需要4秒,并且它需要4秒,它可以跳过剩余部分。如果需要更长的时间,剩下的就是我们将渐渐吃掉的东西。因此:

function chunkProgressFraction(expectedEndT, currentT, expectationFraction) {
    // validate
    if(!expectedEndT) { return 0; }

    // defaults        
    if(!expectationFraction) { expectationFraction = 0.85 }

    // y = k atan(mx)
    // to reach 1.0 at large x:
    // 1.0 = k . atan(+lots) = k . pi/2
    var k = 2.0 / Math.PI;
    // scale the function so that the expectationFraction result happens 
    // at expectedEndT, i.e. 
    // expectationFraction = k * atan(expectedEndT * m)
    // expectedEndT * m = tan(expectationFraction / k)
    var m = Math.tan(expectationFraction / k) / expectedEndT;

    return k * Math.atan(m * currentT);
}

所以,如果我们想要达到100像素,我们希望它需要4个像素,我们希望20%松弛:

progressPixelsThisChunk = 100.0 * 
      chunkProgressValue(4000.0, thisChunkTimeInMilliseconds, 0.8);

一定要使用前一个块所花费的时间来扩展expectedEndT。