requestAnimationFrame with this keyword

后端 未结 7 796
感动是毒
感动是毒 2020-11-27 15:40

I\'m using webkitRequestAnimationFrame but I\'m having trouble using it inside of an object. If I pass the this keyword it will use window

相关标签:
7条回答
  • 2020-11-27 16:06

    Beside bind method, and arrow function solution (offered by Jamaes World's answer), Another (rather old) work around could be:

    var self = this
    window.webkitRequestAnimationFrame(
        function() {
            self.draw()
        }
    );
    
    0 讨论(0)
  • 2020-11-27 16:09

    I'm trying to pass display.draw which is the function in which webkitRequestAnimationFram resides.

    webkitRequestAnimationFrame will presumably call the function you pass in, something like this:

    function webkitRequestAnimationFrame(callback)
    {
        // stuff...
        callback();
        // other stuff...
    }
    

    At this point, you have dissociated (detached) the draw function from its invocation context. You need to bind the function (draw) to its context (the instance of Display).

    You can use Function.bind, but this requires JavaScript 1.8 support (or just use the recommended patch).

    Display.prototype.draw = function()
    {
        // snip...
    
        window.webkitRequestAnimationFrame(this.draw.bind(this));
    };
    
    0 讨论(0)
  • 2020-11-27 16:17

    Now that ES6/2015 is here, if you are using a transpiler then an arrow function has lexical this binding so instead of:

    window.webkitRequestAnimationFrame(this.draw.bind(this));
    

    you can do:

    window.webkitRequestAnimationFrame(() => this.draw());
    

    which is a bit cleaner.

    I've used this effectively with Typescript transpiling to ES5.

    0 讨论(0)
  • 2020-11-27 16:24

    you have not to use "this". Keep it simple.

    var game = {
          canvas:null,
          context:null,
    
        init:function(){
                // init canvas, context, etc
        },      
    
        update:function(){
            //do something
            game.render();                        
            requestAnimationFrame(game.update, game.canvas);        
        },            
    };
    
    0 讨论(0)
  • 2020-11-27 16:26

    I can't guarantee that this is a good idea and that I'm right, but running .bind on every requestAnimationFrame means creating a new function on every iteration. It just doesn't sound right to me.

    That's why in my project I cached the bound function to avoid the anti-pattern.

    Simple example:

    var Game = function () {
        this.counter = 0;
        this.loop = function () {
            console.log(this.counter++); 
            requestAnimationFrame(this.loop);
        }.bind(this);
        this.loop();
    }
    var gameOne = new Game();
    

    If you have a more complex project with prototype inheritance you can still create a cached function with "this" bound in object's constructor

    var Game = function () {
        this.counter = 0;
        this.loopBound = this.loop.bind(this);
        this.loopBound();
    }
    Game.prototype.loop = function () {
        console.log(this.counter++); 
        requestAnimationFrame(this.loopBound);
    }
    var gameOne = new Game();
    

    Thoughts? http://jsfiddle.net/3t9pboe8/ (look in the console)

    0 讨论(0)
  • 2020-11-27 16:26

    how about this:

    Display.prototype.draw = function(){
      this.cxt.clearRect(0, 0, this.canvas.width, this.canvas.height);
      //Animation stuff here.
    
      window.webkitRequestAnimationFrame( $.proxy(function() {this.draw()}, this) );
    };
    

    ...assuming you use jquery

    0 讨论(0)
提交回复
热议问题