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);
};
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));
};
ES6/2015がここにあるので、トランスパイラーを使用している場合、矢印関数にはレキシカルthis
バインディングがあるので、次の代わりに:
window.webkitRequestAnimationFrame(this.draw.bind(this));
できるよ:
window.webkitRequestAnimationFrame(() => this.draw());
少しきれいです。
ES5へのTypeScriptトランスパイルでこれを効果的に使用しました。
これが良い考えであり、私が正しいことを保証することはできませんが、すべての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/ (コンソールを確認)
これはどう:
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を使用すると仮定
「これ」を使う必要はありません。複雑にしないでおく。
var game = {
canvas:null,
context:null,
init:function(){
// init canvas, context, etc
},
update:function(){
//do something
game.render();
requestAnimationFrame(game.update, game.canvas);
},
};
bind
メソッドと矢印関数ソリューション(Jamaes Worldの回答により提供)の他に、別の(かなり古い)回避策は次のとおりです。
var self = this
window.webkitRequestAnimationFrame(
function() {
self.draw()
}
);