2011-05-19 91 views
35

我使用webkitRequestAnimationFrame但我使用一个对象的内部有问题。如果我通过了this关键字它将使用window,我不能找到一种方法它使用指定的对象,而不是。requestAnimationFrame与此关键字

例子:

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

回答

69

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

webkitRequestAnimationFrame大概会打电话给你传递的功能,这样的事情:

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

此时,您已将其draw函数与其调用上下文分离(分离)。你需要的功能(draw)绑定到其上下文(的Display实例)。

您可以使用Function.bind,但是这个requires JavaScript 1.8 support(或只是使用建议的补丁)。

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

    window.webkitRequestAnimationFrame(this.draw.bind(this)); 
}; 
+0

我想通过'display.draw'这是'webkitRequestAnimationFram'驻留的函数。 – Ryan 2011-05-19 21:52:29

+1

哦,我想我看到了问题:你可以传递函数,但'webkitRequestAnimationFrame'稍后会调用它,'this'不会指向正确的对象,因为你已经从它的对象中“分离”了函数。查看我的编辑(待定)。 – 2011-05-19 21:54:14

+0

'bind'方法完美工作(从来不知道这个,thnx:]),但是通过'this.draw();'方法仍然会抛出一个错误。 '未捕获的类型错误:对象[对象DOMWindow]没有方法'绘制' – Ryan 2011-05-19 22:09:43

3

这个怎么样:

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

+0

如何在没有jquery的情况下使用它?我试图使用绑定,但它的最大堆栈大小超过错误。 – Dramorian 2015-07-14 11:35:34

0

你还没有使用 “这个”。 保持简单。

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

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

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

不错。我需要一个方法可以从类外部访问,所以我使用了这个方法:var update = this.update = function(){render(); requestAnimationFrame(更新); }' – 2013-11-11 14:55:13

3

我不能保证,这是一个好主意,我是正确的,但.bind运行对每个requestAnimationFrame意味着在每次迭代中创建一个新函数。这听起来并不正确。

这就是为什么在我的项目,我缓存绑定功能,避免反模式。

简单的例子:

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

如果你有原型继承一​​个更复杂的项目,您还可以创建一个缓存的功能“这”必将在对象的构造

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/(在控制台看)现在

+1

我修改了你的[fiddle](http://jsfiddle.net/uuvqju4L/1/)到(我认为)测试缓存绑定函数和不区分。我很惊讶地发现两者(Firefox 47,Chrome 52和IE 11)的性能差不多。看起来好像由'bind'创建的函数由浏览器缓存,但我不知道实际发生了什么。我甚至尝试单独运行,以避免浏览器对'requestAnimationFrame'的优化造成干扰。 – 2016-08-29 22:48:20

+1

@SeanH在这种情况下,“循环”是一个非常简单的功能,由计数器增量和条件检查组成。我想知道,如果在每一次更复杂的函数迭代中使用“绑定”会产生更大的差异。请求动画帧永远不会超过60fps的这种做法的收益可能是微不足道的。 – Pawel 2016-08-30 09:32:40

9

是ES6/2015这里,如果你使用的是transpiler然后一个箭头功能词汇this绑定,而不是:

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

,你可以这样做:

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

这是有点清洁器。

我已经有效地将这个与Typescript转换为ES5。

+0

这是我现在使用的。 – Ryan 2016-06-19 12:03:47