running requestAnimationFrame from within a new object
Asked Answered
D

2

9

I'm having trouble running an animation. This is inside var ob1 = function() {};. When called, it runs for a while and then I get the error Uncaught RangeError: Maximum call stack size exceeded. However, this same structure has no problems running outside of the object.

/////////////// Render the scene ///////////////
this.render = function (){

        renderer.render(scene,camera);
        if(isControls == true) controls.update(clock.getDelta());
        this.animate();
        //console.log(true);
        requestAnimationFrame(this.render());
}

/////////////// Update objects ///////////////
this.animate = function (){
        console.log("!");
}
Daedalus answered 18/10, 2013 at 21:39 Comment(1)
requestAnimationFrame expects a callback, you're just passing undefined.Taka
K
24

You should pass a function reference to requestAnimationFrame, not invoke the function:

requestAnimationFrame(this.render);

Since you're using this inside render, you'll probably need bind:

requestAnimationFrame(this.render.bind(this));

Your version is causing a Stack Overflow (the function is calling itself synchronously, until the call stack is full).


Kktp answered 18/10, 2013 at 21:42 Comment(5)
That's actually what I tried first, because that's what I normally do, but it doesn't work. It runs only 1 time and tells me this.animate() doesn't exist, after running this.animate(). If I put it as the first thing, I get Uncaught TypeError: Type error cleanedupmenufunctions.php:167 renderDaedalus
I just updated my answer, you need a bound function, with a fixed this value.Kktp
Ah, the line requestAnimationFrame(this.render.bind(this)); works great! No errors after several refreshes.Daedalus
Note that bind is not supported on older browsers. The MDN link I provided includes a polyfill.Kktp
You don't want to use bind this way as you're creating a new function object every time you call bind. Instead you want to bind beforehand at init time as in const render = this.render.bind(this); then in your loop call requestAnimationFrame(render). You could also do it the react way, in your constructor do this.render = this.render.bind(this); then you can call requestAnimationFrame(this.render);Holozoic
S
0

Something I did to get this to run from a class that I saw from another example was to do this.

requestAnimationFrame(() => {
      this.animate()
})

This seems to get around the issue as well without any issues!

Here is a threeJS example of me using this from within a class

https://jsfiddle.net/gentleman_goat66/o5wn3bpf/107/

Seddon answered 5/4, 2023 at 23:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.