web-dev-qa-db-ja.com

このキーワードを含むrequestAnimationFrame

webkitRequestAnimationFrameを使用していますが、オブジェクト内で使用できません。 thisキーワードを渡すと、windowが使用され、代わりに指定されたオブジェクトを使用する方法が見つかりません。

例:

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

  window.webkitRequestAnimationFrame(this.draw);
};

私もこれを試しましたが、役に立ちませんでした:

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

  var draw = this.draw;
  window.webkitRequestAnimationFrame(draw);
};
45
Ryan

WebkitRequestAnimationFramが存在する関数であるdisplay.drawを渡そうとしています。

webkitRequestAnimationFrameはおそらく、次のような、渡した関数を呼び出します。

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

この時点で、draw関数を呼び出しコンテキストから分離(切り離し)しています。関数(draw)をそのコンテキスト(Displayのインスタンス)にバインドする必要があります。

Function.bind ですが、これは JavaScript 1.8のサポートが必要です (または推奨パッチを使用するだけです)。

Display.prototype.draw = function()
{
    // snip...

    window.webkitRequestAnimationFrame(this.draw.bind(this));
};
85
Matt Ball

ES6/2015がここにあるので、トランスパイラーを使用している場合、矢印関数にはレキシカルthisバインディングがあるので、次の代わりに:

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

できるよ:

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

少しきれいです。

ES5へのTypeScriptトランスパイルでこれを効果的に使用しました。

22
James World

これが良い考えであり、私が正しいことを保証することはできませんが、すべてのrequestAnimationFrameで.bindを実行することは、すべての反復で新しい関数を作成することを意味します。それは私には正しく聞こえません。

そのため、私のプロジェクトでは、アンチパターンを回避するためにバインドされた関数をキャッシュしました。

簡単な例:

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

プロトタイプ継承を伴うより複雑なプロジェクトがある場合でも、オブジェクトのコンストラクターで「this」がバインドされたキャッシュ関数を作成できます

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();

考え? http://jsfiddle.net/3t9pboe8/ (コンソールを確認)

5
Pawel

これはどう:

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) );
};

... jqueryを使用すると仮定

3
bogdan

「これ」を使う必要はありません。複雑にしないでおく。

var game = {
      canvas:null,
      context:null,

    init:function(){
            // init canvas, context, etc
    },      

    update:function(){
        //do something
        game.render();                        
        requestAnimationFrame(game.update, game.canvas);        
    },            
};
0
Tomáš

bindメソッドと矢印関数ソリューション(Jamaes Worldの回答により提供)の他に、別の(かなり古い)回避策は次のとおりです。

var self = this
window.webkitRequestAnimationFrame(
    function() {
        self.draw()
    }
);
0
MortezaE