setTimeout - 计数器以指数方式增加速度

时间:2016-08-31 08:37:46

标签: javascript jquery math setinterval

我想要做的是在给定时间内(例如2秒)打印出一系列数字(例如1-100)的函数。超级容易。

最难的部分是序列动画应该缓慢开始并且以指数方式加速。这就是我到目前为止所做的:

var animationLength = 2000; //ms

var counter = 0,
    counterEnd = 100,
    countInterval = animationLength / counterEnd; // 20ms

function animate() {
  $('#result').text(counter++);
  if (counter <= counterEnd) {

    //Calculate here dynamically newInterval
    var newInterval = countInterval;

    countInterval = newInterval;
    setTimeout(animate, newInterval);
  }
}

animate();

所以,现在countInterval始终 20ms ,但它应该是可变的,呈指数级递减。例如:

counter = 1; => countInterval = 40ms //not sure about that
...
counter = 100; => countInterval = 1ms

这些区间的总和必须 2000ms

https://jsfiddle.net/fvxf7mby/5/

更新:

感谢@Mats Lind我终于找到了。这是最终代码(JSFIDDLE

var animationLength = 2000; //ms

var counter = 0,
    counterEnd = 100,
    countInterval = animationLength / counterEnd, // 20 ms,
    a = 1.05; //speed factor

var summatory = 0;

function animate() {
  $('#result').text(counter++);
  if (counter <= counterEnd) {

    //that's the formula:
    var newInterval = (animationLength-summatory) / ( (a - Math.pow(a, -(counterEnd-1))) / (a-1))

    summatory += newInterval;
    countInterval = newInterval;
    setTimeout(animate, newInterval);
  } else {
    $('#summatory').text(summatory); //should be 2000
  }
}

animate();

3 个答案:

答案 0 :(得分:2)

Looking at the "hardest part", the math question about speeding up exponentially:

With time-interval inversely proportional to speed, we like the time-interval to decrease. Exponentially mean a decrease with the same factor between each interval.

Call the factor 1/a and set the first time-interval to b, then next time-interval will be be b/a, the third b/a^2 and the n:th b/a^(n-1).

Total time for N timesteps is b*(a-a^-(N-1))/(a-1) (summation formula for an exponential series), excel formula; =(a-a^-(N-1))/(a-1)

Now we know total time 2000ms and number of steps 100, and have two unknown, b and a, but only one equation. So we can set a and have b given via the equation above b=total_time/((a-a^-(N-1))/(a-1)). The more we want time to "accelerate" the higher we should set a. To conclude:

time interval length for interval n>0: b/a^(n-1)

total_time: choose, in this example total_time = 2000ms

N: choose, in this example N=100

a: choose, higher the faster you want speed to increase

b=total_time/((a-a^-(N-1))/(a-1)).

Try for instance a = 1.05 which gives b = 95.96788204ms and all timesteps:

95.96788204 91.39798289 87.04569799 82.90066476 78.95301405 75.19334672 71.61271116 68.20258206 64.95484005 61.86175243 58.9159547 56.11043304 53.43850766 50.89381682 48.47030173 46.16219213 43.9639925 41.87046905 39.87663719 37.97774971 36.16928543 34.44693851 32.8066081 31.24438867 29.75656064 28.33958156 26.99007768 25.70483588 24.48079608 23.31504388 22.2048037 21.14743209 20.14041152 19.1813443 18.26794696 17.39804472 16.5695664 15.78053943 15.02908517 14.31341445 13.63182328 12.98268884 12.36446556 11.77568149 11.21493475 10.68089024 10.17227642 9.687882303 9.226554574 8.787194832 8.368756983 7.970244746 7.590709282 7.229246935 6.884997081 6.557140077 6.244895312 5.947519344 5.664304138 5.394575369 5.137690828 4.893038884 4.660037032 4.438130507 4.226790959 4.025515199 3.833823999 3.651260951 3.477391382 3.311801316 3.154096492 3.003901421 2.860858496 2.724627139 2.594882989 2.471317133 2.353635365 2.24155749 2.134816657 2.033158721 1.936341639 1.844134894 1.756318947 1.672684712 1.593033059 1.517174342 1.444927944 1.376121852 1.31059224 1.248183085 1.188745796 1.132138853 1.078227479 1.026883313 0.977984108 0.931413436 0.887060415 0.844819443 0.804589946 0.766276139

答案 1 :(得分:0)

使用setTimeout

会更容易

var animationLength = 1000; // 1 second
var counter = 0;
var counterEnd = 100;

function animate() {
  // Do stuff
  $('#output').text(counter++);
  animationLength *= 0.5; // not exponential - but speed will half on each iteration
  if (counter <= counterEnd) { // Stopping condition
    setTimeout(animate, animationLength);
  }
}

animate(); // Starting the "loop"
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>

答案 2 :(得分:0)

使用A.Wolf评论中提到的小提琴。根据您的要求编辑了他的jsfiddle

var counter = 1000;

var num = 1;
var myFunction = function(){
    counter = counter -20;
    
   $("#result").html(num);
   num++;
    if(num <=100)
    {
    timeout = setTimeout(myFunction, counter);
    }
}

var timeout = setTimeout(myFunction, counter);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="result">

</div>

相关问题