setTimeout - 计数器以指数方式增加速度
setTimeout - counter increasing speed exponentially
我正在尝试做的是一个在给定时间(例如 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();
使用 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>
使用 A.Wolf 的评论中提到的 fiddle。刚刚根据您的要求编辑了他的 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>
看"hardest part",关于指数加速的数学题:
由于时间间隔与速度成反比,我们希望时间间隔减少。指数表示每个间隔之间具有相同因子的减少。
调用因子1/a,将第一个时间间隔设为b,则下一个时间间隔为b/a,第三个b/a^2,第一个n:th b/a^(n-1).
N个时间步的总时间为b*(a-a^-(N-1))/(a-1)(指数级数求和公式),excel公式; =(a-a^-(N-1))/(a-1)
现在我们知道总时间为 2000ms,步数为 100,并且有两个未知数 b 和 a,但只有一个方程。所以我们可以设置 a 并通过上面的等式 b=total_time/((a-a^-(N-1))/(a-1)) 给出 b。我们越是想要"accelerate"的时间就应该设置的越高。总结:
间隔 n>0 的时间间隔长度:b/a^(n-1)
total_time:选择,在本例中total_time = 2000ms
N:选择,本例N=100
a:选择,越高越快你想要的速度提升
b=total_time/((a-a^-(N-1))/(a-1))。
例如尝试 a = 1.05,它给出 b = 95.96788204ms 和所有时间步长:
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
我正在尝试做的是一个在给定时间(例如 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();
使用 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>
使用 A.Wolf 的评论中提到的 fiddle。刚刚根据您的要求编辑了他的 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>
看"hardest part",关于指数加速的数学题:
由于时间间隔与速度成反比,我们希望时间间隔减少。指数表示每个间隔之间具有相同因子的减少。
调用因子1/a,将第一个时间间隔设为b,则下一个时间间隔为b/a,第三个b/a^2,第一个n:th b/a^(n-1).
N个时间步的总时间为b*(a-a^-(N-1))/(a-1)(指数级数求和公式),excel公式; =(a-a^-(N-1))/(a-1)
现在我们知道总时间为 2000ms,步数为 100,并且有两个未知数 b 和 a,但只有一个方程。所以我们可以设置 a 并通过上面的等式 b=total_time/((a-a^-(N-1))/(a-1)) 给出 b。我们越是想要"accelerate"的时间就应该设置的越高。总结:
间隔 n>0 的时间间隔长度:b/a^(n-1)
total_time:选择,在本例中total_time = 2000ms
N:选择,本例N=100
a:选择,越高越快你想要的速度提升
b=total_time/((a-a^-(N-1))/(a-1))。
例如尝试 a = 1.05,它给出 b = 95.96788204ms 和所有时间步长:
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