Cabbibo
Cabbibo

Reputation: 1411

requestAnimationFrame, Non Globally?

So I am trying to create an 'Animator' Module, that basically makes it easy to start and stop requestAnimationFrame Loops

define(function(require, exports, module) {
  var a = require( 'js/lib/stats.min.js'  );

  function Animator(){

    this.stats = new Stats();
    this.stats.domElement.style.position  = 'absolute';
    this.stats.domElement.style.bottom    = '0px';
    this.stats.domElement.style.right     = '0px';
    this.stats.domElement.style.zIndex   = '999';

    this.requestAnimationFrame = requestAnimationFrame;

    document.body.appendChild( this.stats.domElement );


  }

  Animator.prototype.start = function(){
    this.animate( this );
  }

  Animator.prototype.stop = function(){

    if (requestId) {
      cancelAnimationFrame(this.requestId);
      this.requestId = undefined;
    }

  }

  Animator.prototype.animate = function( ){

    this.update();

    this.requestId = this.requestAnimationFrame( this.animate );

 }


 // Empty function, because it will be user defined
 Animator.prototype.update = function(){

 }

  return Animator

});

As you can tell I'm doing some illegal things here:

First Off I am trying to assign requestAnimationFrame to this.requestAnimationFrame. This is because on the .animate function of the prototype, I want to be able to access the update function of this object. The problem is that when I do this, like so:

Animator.prototype.animate = function( ){

  whichAnimator.update();

  whichAnimator.requestId = requestAnimationFrame( whichAnimator.animate( whichAnimator ) );

}

I get a maximum stack call exceeded.

I guess I am wondering what the best way is to do this, because at this point I obviously have no idea what I am doing.

If you have any questions please ask, and thanks in advance for your time!

Upvotes: 1

Views: 952

Answers (2)

David Hellsing
David Hellsing

Reputation: 108472

requestAnimationFrame does not work like setInterval, the requestID will be different for each call. So there is really no point in assigning it to the context.

I find it easier to gasp if you simply run a single requestAnimationFrame globally, then call whatever animations you have running in the loop. Here is some sketchy code:

var animations = {}; // holder for animation functions

(function loop() {
    for(var id in animations) {
        animations[id]();
    }
    requestAnimationFrame(loop);
}());

function start(fn) {
    var id = +new Date();
    animations[id] = fn;
    return id;
}
function stop(id) {
    if (animations.hasOwnProperty(id)) {
        delete animations[id];
    }
}

Upvotes: 1

Cabbibo
Cabbibo

Reputation: 1411

.bind did it!

Thanks @kalley

Animator.prototype.start = function(){
  this.running = true;
  this.animate();
}

Animator.prototype.stop = function(){
  this.running  = false;
}

Animator.prototype.animate = function( ){

  this.stats.update();
  this.update();

  if( this.running == true ){ 
    window.requestAnimationFrame( this.animate.bind( this ) );
  }

}

Upvotes: 2

Related Questions