我终于明白在threejs中为什么requestAnimationFrame(callback)放在callback中第一行也不会造成死循环的原因了



         animationloop();
         function animationloop(){
         	requestAnimationFrame(animationloop);
         	renderer.render(scene,camera); 
         }

因为这个回调函数(比如上面这个animationloop)不是立即执行的。
它的执行时间点是在浏览器下次重绘之前。所以当时间还没抵达重绘之前那一刻的时候,就不会触发。有点类似于setInterval(function, milliseconds)
还可以把requestAnimationFrame(animationloop)理解为开启一个动画渲染定时器,只有在即将重绘那一刻,才触发animationloop进行动画帧渲染。
当然,实际负责渲染的是renderer.render(scene,camera)这个函数,而且每次只渲染一帧。这就会导致,如果把requestAnimationFrame(animationloop)放在animationloop这个函数外面,就没法产生动画的问题。

而只有当把requestAnimationFrame(animationloop)放在animationloop这个函数里面的时候,才能确保动画的产生。它的执行逻辑是这样的:
1.
function animationloop(){
requestAnimationFrame(animationloop);
renderer.render(scene,camera);
}该函数被定义好。
2.接着运用animationloop()对其进行调用。
3.执行animationloop()内部的代码,最先执行到requestAnimationFrame(animationloop);这一行。
4.requestAnimationFrame(animationloop)表示开启一个动画渲染定时器,并预留一个animationloop函数在浏览器下次重绘前待执行。(★特别注意:虽然这个animationloop没有立即执行,但requestAnimationFrame()本身是立即执行了的。就像开启定时器一样,定时器内部的回调函数虽然没有立即执行,但定时器函数是在被调用的一瞬间就已经开启了一个定时器。所以,实际上产生了requestAnimationFrame()的自我调用,只不过下一次requestAnimationFrame()调用是在间隔一个浏览器重绘时间后才执行。既然有自我调用,那必然就形成了循环,画面自然就能动起来了。)
5.执行renderer.render(scene,camera); 这行代码。
6.当浏览器即将重绘那一刻来临,再次触发animationloop(这里可以理解为,消耗了第一个动画渲染定时器,也就是第一个requestAnimationFrame(),它的任务彻底完成了。此时,工作被转交给第二个requestAnimationFrame(),用来绘制第二帧,当第二帧绘制完成,第二个requestAnimationFrame()的任务也完成了,再把工作转交给第三个requestAnimationFrame(),剩下的依此类推。)

我之前一直不理解为什么requestAnimationFrame()放renderer.render(scene,camera);这一行之前还能成功渲染出动画。我想的是:它一直自我调用,那不成了每次都只能执行自己,就像requestAnimationFrame(requestAnimationFrame(requestAnimationFrame(……)))这样,从而始终执行不到下面的renderer.render(scene,camera);
就是因为没有理解到requestAnimationFrame()内部的这个回调函数(在我的例子当中就是这个animationloop)并非瞬时执行,它其实是在renderer.render(scene,camera);这行代码执行完之后才执行的。
用线程的思考方式来理解的话,就相当于主线程执行到requestAnimationFrame()这一行的时候,在后台线程开启了一个计时器,计时器同步进行计时,并预留一个待执行任务(其触发条件是,60分之一秒,或者75分之一秒后,具体时间依显示器刷新率而定),然后继续执行下面的renderer.render(scene,camera); 代码,等到下一帧重绘前一刹那(其实就是计时器数了60分之一秒或者75分之一秒后),再把后台线程中的待执行任务加载到主线程中,然后开始执行它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值