[英]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
謝謝你們 !
Mourtaza。
您遇到了不幸的浮點數學運算的情況
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
為什么會得到這么小的數字? 請問。 發生這種情況是因為浮點數不准確,因為不可能像整數一樣將小數點“保存到末尾”。 例如,假設1/3
具有無限數量的小數。 在這里,您可以了解有關JavaScript和浮點精度的更多信息: 處理Javascript中的浮點精度
另一個問題是有一個負角(雖然您實際上檢查了負角,但角度很小,但仍然是負數)。 發生這種情況是因為您在增加/減小之前先檢查了負角,因此,如果乘數為負,並且角度為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();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.