2017-07-07 35 views
1

方法,當我在控制檯打電話app.update()這個工作,但是當我使用​​有一個錯誤:傳類在requestAnimationFrame

Uncaught TypeError: Cannot read property 'drops' of undefined at update (oee.html:40)

它同時使用setInterval工作。

我錯過了什麼?

<!DOCTYPE html> 
<html> 
    <head> 
    <meta charset="utf-8"> 
    <title></title> 
    <style media="screen"> 
     *{ 
     margin:0; 
     padding:0; 
     } 
     #app{ 
     height:100vh; 
     width:100vw; 
     background-color: red; 
     overflow: hidden; 
     } 
     .drop{ 
     position:absolute; 
     background-color:#fff; 
     top:10px; 
     width: 5px; 
     } 
    </style> 
    </head> 
    <body> 
    <div id="app"> 
    </div> 
    <script type="text/javascript"> 
     class App{ 
     constructor(){ 
      this.el = document.getElementById("app"); 
      this.height=this.el.clientHeight; 
      this.width=this.el.clientWidth; 
      this.drops=[]; 
      for(var i=0;i<100;i++){ 
      this.drops.push(new Drop(this.height,this.width)); 
      } 
     } 
     update(){ 
      this.drops.forEach(function(drop){ 
      drop.update(); 
      }); 
     } 
     } 

     class Drop{ 
     constructor(appHeight,appWidth){ 
      this.speed=Math.random(); 
      this.el=document.createElement("div"); 
      this.el.setAttribute("class","drop"); 
      this.el.style.height=(Math.random()*10+5)+"px"; 
      this.el.style.left=(Math.random()*appWidth)+"px"; 
      this.appHeight=appHeight; 
      document.getElementById("app").appendChild(this.el); 
      this.el.style.top=0; 
     } 

     update(){ 
      this.top=this.el.style.top.replace("px",""); 
      this.el.style.top=(this.top>this.appHeight)?"0px":(parseFloat(this.top) + parseFloat(this.speed*300))+"px"; 
     } 
     } 
     var app=new App(); 
     requestAnimationFrame(app.update); 
    </script> 
    </body> 
</html> 
+0

[requestAnimationFrame與此關鍵字](https://stackoverflow.com/questions/6065169/requestanimationframe-with-this-keyword)的可能的複製| '使用requestAnimationFrame的時候,所以你必須this'改變'.bind()'等等這樣的功能:https://codepen.io/anon/pen/QgVxxK – yuriy636

回答

1

當你調用app.update(),您呼叫的update功能作爲app對象的方法。

但在問題中顯示的代碼不會調用你的函數的方法:

requestAnimationFrame(app.update); 

當你寫app.update(不使用括號),您是剛開始來的app.update功能參考獨立功能。它失去了與對象app的連接。當requestAnimationFrame()以後調用你update功能,它只是直接調用該函數沒有任何this對象。所以,當update引用this.drops失敗。

你沒有列出您的setInterval()版本,但有一點我們可以肯定的是,它沒有這個樣子的:

setInterval(app.update, 10); 

如果這是你使用的代碼,它會與requestAnimationFrame()相同的問題。你可能已經寫了這樣的事情:

setInterval(function() { 
    app.update(); 
}, 10); 

現在你setInterval()回調是匿名函數,而函數調用app.update()的方法

您可以使用requestAnimationFrame()做同樣的事情,但每次需要等待另一個幀時需要撥打requestAnimationFrame()。換句話說,它更像setTimeout()而非setInterval()。所以它可能看起來像這樣:

var updater = function() { 
    app.update(); 
    requestAnimationFrame(updater); // for subsequent frames 
}; 

requestAnimationFrame(updater); // for the first frame 

現在您的代碼應該按預期工作。

下面是一個updated version of yuriy636's CodePen test動畫工作。