当我在控制台中调用app.update()
时,这有效,但当我使用requestAnimationFrame
时出现错误:
未捕获的TypeError:无法读取属性' drop'更新时未定义的内容(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 :(得分: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动画制作工作。