requestAnimationFrame 没有按预期工作
requestAnimationFrame doesn't work as expected
我的脚本有问题,我不明白哪里出了问题。
这里是:
let angle = 0
let multiplier = .01
function raf() {
if(angle >= 1 || angle < 0) {
multiplier = - multiplier
}
angle = angle + multiplier
if(angle < 0) console.log(angle)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
目的是将角度提高0.01,当达到1时,应该减少到0,然后再提高到1。
我有时会得到一个负角 (-8.etc),我不明白为什么(console.log 应该表明了这一点)。
我为此做了一支笔:https://codepen.io/mourtazag/pen/QvjjLy
谢谢大家!
穆尔塔扎。
您遇到了不幸的浮点数学问题
0.94 - 0.01
0.9299999999999999
这些错误会随着您越来越多地减去 0.01 而复合,所以最后不是执行 0.01 - 0.01 会得到 0,代码而是执行类似
的操作
0.009999999999999247 - 0.01
略显消极。如果你需要这样限制,你可能只用 Math.max(0, yourValue) 和 Math.min(1, yourValue) 限制最小值和最大值。
这是一个浮点问题
var a = 0;
for (var i = 0; i < 100; ++i) {
a += 0.01;
}
console.log(a);
for (var i = 0; i < 101; ++i) {
a -= 0.01;
}
console.log(a);
a += 0.01;
console.log(a);
打印
1.0000000000000007
-0.010000000000000087
-8.673617379884035e-17
考虑使用整数或时钟并从中计算角度
您没有收到 -8
,您收到 -8.XXXXXXe-17
。注意最后的 e-17
。那是科学记数法,所以你的数字实际上是 -0.00000000000000008XXXXX
。您可以使用 angle.toFixed(20)
查看没有科学记数法的浮点数。该数字是您要显示的小数位数。
如果只增加和减少 0.01
,为什么会得到这么小的数字?请问。发生这种情况是因为浮点数不精确,因为小数不可能是 "saved to the end",不像整数。例如,想想 1/3
有无限多的小数。在这里您可以阅读更多关于 JavaScript 和浮点精度的信息:Dealing with float precision in Javascript
另一个问题是有一个负角(这么小,但仍然是负的,尽管你实际上检查了负角)。发生这种情况是因为您在 increasing/decreasing 之前检查了负角,所以如果您的乘数为负而角度为 0.0001whatever
(由于浮点精度问题),它仍然高于零,所以你的乘数仍然是负的,但实际上比你的角度大,所以当应用乘数时,角度将是负的。
我能想到的办法来解决这个问题:
let angle = 0
let multiplier = .01
function raf() {
angle = angle+multiplier;
if(angle > 1 || angle < 0) {
multiplier = -multiplier
angle = angle<0?0:1;
}
console.log(angle.toFixed(20))
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
有了这个,你可以在处理后检查你的角度是否在限制范围内,这样你就可以克服精度问题:https://codepen.io/anon/pen/eWppGy
另一种方法是使用整数(因为它们没有精度问题,正如我上面所说的)并在使用它时将角度除以 100,如下所示:
let angle = 0
let multiplier = 1
function raf() {
angle = angle+multiplier;
if(angle >= 100 || angle <= 0) {
multiplier = -multiplier;
angle = angle<=0?0:100;
}
console.log(angle/100)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
题外话:换个角度。作为经过时间的函数而不是增量变化。
let start = Date.now();
let speed = 1 / 10000; //1 in every 10 seconds
function raf() {
let v = (Date.now() - start) * speed;
let angle = v&1? 1-v%1: v%1;
document.body.textContent = "Angle: " + angle.toFixed(3);
requestAnimationFrame(raf);
}
//or with some sugar:
speed = 180/10000;
function raf() {
let minAngle = -90, maxAngle = 90, delta = maxAngle - minAngle;
let v = (Date.now() - start) * speed;
let angle = (v/delta)&1? maxAngle-v%delta: minAngle + v%delta;
document.body.textContent = "angle: " + angle.toFixed(3);
requestAnimationFrame(raf);
}
raf();
或者加点糖;当我们不讨论从 0
到 1
的范围时的整个计算
let start = Date.now();
let speed = 180 / 10000;
let minAngle = -30, maxAngle = 45;
function raf() {
let delta = maxAngle - minAngle;
let v = (Date.now() - start) * speed;
let backwards = (v/delta)&1;
let angle = backwards? maxAngle - v%delta: minAngle + v%delta;
document.body.textContent = "angle: "+ angle.toFixed(3) +", direction: " + (backwards? "backward": "forward");
requestAnimationFrame(raf);
}
raf();
我的脚本有问题,我不明白哪里出了问题。
这里是:
let angle = 0
let multiplier = .01
function raf() {
if(angle >= 1 || angle < 0) {
multiplier = - multiplier
}
angle = angle + multiplier
if(angle < 0) console.log(angle)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
目的是将角度提高0.01,当达到1时,应该减少到0,然后再提高到1。
我有时会得到一个负角 (-8.etc),我不明白为什么(console.log 应该表明了这一点)。
我为此做了一支笔:https://codepen.io/mourtazag/pen/QvjjLy
谢谢大家!
穆尔塔扎。
您遇到了不幸的浮点数学问题
0.94 - 0.01
0.9299999999999999
这些错误会随着您越来越多地减去 0.01 而复合,所以最后不是执行 0.01 - 0.01 会得到 0,代码而是执行类似
的操作0.009999999999999247 - 0.01
略显消极。如果你需要这样限制,你可能只用 Math.max(0, yourValue) 和 Math.min(1, yourValue) 限制最小值和最大值。
这是一个浮点问题
var a = 0;
for (var i = 0; i < 100; ++i) {
a += 0.01;
}
console.log(a);
for (var i = 0; i < 101; ++i) {
a -= 0.01;
}
console.log(a);
a += 0.01;
console.log(a);
打印
1.0000000000000007
-0.010000000000000087
-8.673617379884035e-17
考虑使用整数或时钟并从中计算角度
您没有收到 -8
,您收到 -8.XXXXXXe-17
。注意最后的 e-17
。那是科学记数法,所以你的数字实际上是 -0.00000000000000008XXXXX
。您可以使用 angle.toFixed(20)
查看没有科学记数法的浮点数。该数字是您要显示的小数位数。
如果只增加和减少 0.01
,为什么会得到这么小的数字?请问。发生这种情况是因为浮点数不精确,因为小数不可能是 "saved to the end",不像整数。例如,想想 1/3
有无限多的小数。在这里您可以阅读更多关于 JavaScript 和浮点精度的信息:Dealing with float precision in Javascript
另一个问题是有一个负角(这么小,但仍然是负的,尽管你实际上检查了负角)。发生这种情况是因为您在 increasing/decreasing 之前检查了负角,所以如果您的乘数为负而角度为 0.0001whatever
(由于浮点精度问题),它仍然高于零,所以你的乘数仍然是负的,但实际上比你的角度大,所以当应用乘数时,角度将是负的。
我能想到的办法来解决这个问题:
let angle = 0
let multiplier = .01
function raf() {
angle = angle+multiplier;
if(angle > 1 || angle < 0) {
multiplier = -multiplier
angle = angle<0?0:1;
}
console.log(angle.toFixed(20))
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
有了这个,你可以在处理后检查你的角度是否在限制范围内,这样你就可以克服精度问题:https://codepen.io/anon/pen/eWppGy
另一种方法是使用整数(因为它们没有精度问题,正如我上面所说的)并在使用它时将角度除以 100,如下所示:
let angle = 0
let multiplier = 1
function raf() {
angle = angle+multiplier;
if(angle >= 100 || angle <= 0) {
multiplier = -multiplier;
angle = angle<=0?0:100;
}
console.log(angle/100)
requestAnimationFrame(raf)
}
requestAnimationFrame(raf)
题外话:换个角度。作为经过时间的函数而不是增量变化。
let start = Date.now();
let speed = 1 / 10000; //1 in every 10 seconds
function raf() {
let v = (Date.now() - start) * speed;
let angle = v&1? 1-v%1: v%1;
document.body.textContent = "Angle: " + angle.toFixed(3);
requestAnimationFrame(raf);
}
//or with some sugar:
speed = 180/10000;
function raf() {
let minAngle = -90, maxAngle = 90, delta = maxAngle - minAngle;
let v = (Date.now() - start) * speed;
let angle = (v/delta)&1? maxAngle-v%delta: minAngle + v%delta;
document.body.textContent = "angle: " + angle.toFixed(3);
requestAnimationFrame(raf);
}
raf();
或者加点糖;当我们不讨论从 0
到 1
let start = Date.now();
let speed = 180 / 10000;
let minAngle = -30, maxAngle = 45;
function raf() {
let delta = maxAngle - minAngle;
let v = (Date.now() - start) * speed;
let backwards = (v/delta)&1;
let angle = backwards? maxAngle - v%delta: minAngle + v%delta;
document.body.textContent = "angle: "+ angle.toFixed(3) +", direction: " + (backwards? "backward": "forward");
requestAnimationFrame(raf);
}
raf();