Question

I've hit a wall trying to figure this out. I'm new to OO Javascript and trying to put together my first class/object. I'm trying to create a canvas loader and it's not working. I've narrowed down the error to the requestAnimationWindow portion inside my animate function in my clock class. I get a Object [object global] has no method 'animate' error. Here is my code.

HTML:

<div id="loader"><canvas id="showLoader" width="250" height="250"></canvas><div id="showTimer"><p id="elapsedTime">
  <script>
    var clockTest = new clock(document.getElementById("showLoader"), 0, 100);
    clockTest.animate();
  </script>

</p></div></div>

Javascript:

function clock(canvas, curPerc, endPrecent){

var showPerc = document.getElementById("elapsedTime");
this.canvas = document.getElementById("showLoader");

var context = this.canvas.getContext('2d');
var x = this.canvas.width / 2;
var y = this.canvas.height / 2;
var radius = 75;
this.curPerc = 0;
this.endPercent = 110;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;


context.lineWidth = 10;
context.strokeStyle = '#ed3f36';


this.animate = function(current) {

    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    this.context.beginPath();
    this.context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
    this.context.stroke();
    this.curPerc++;

    if(this.curPerc < this.endPercent) {
        requestAnimationFrame(function () {
            this.animate(curPerc / 100);
            showPerc.innerHTML = this.curPerc + '%';
        });
    }
};

}

Any tips is appreciated. Thanks!

Était-ce utile?

La solution

It is to do with the context of this in the anonymous function you pass to requestAnimationFrame, its not the this you think. Use a closure i.e.

this.animate = function(current) {
    var self = this; //<-- Create a reference to the this you want
    self.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    /.. etc, etc..

    if(self.curPerc < self.endPercent) {
        requestAnimationFrame(function () {
            self.animate(self.curPerc / 100); //<-- and use it here
            showPerc.innerHTML = self.curPerc + '%'; //<-- and here
        });
    }
};

On a couple of other points, I would try to structure the object a bit better, you don't seem to be keeping reference to the properties correctly. The parameters you passed in , are not store on the object, and you are not storing the context correctly. Something like:

function clock(canvas, curPerc, endPrecent) {
    var self = this;
    // Set object properties here, i.e. from the parameters passed in
    // Note also, anything that is a property (i.e. this. ) is public, can be accessed from otuside this object,
    // whereas variable declared with var , are privte, can only be access within this object
    self.canvas = canvas;
    self.curPerc = curPerc;
    self.endPercent = endPrecent;
    self.context = self.canvas.getContext('2d'); //needs to be store like this, if you want to access below as this.context
    self.context.lineWidth = 10;
    self.context.strokeStyle = '#ed3f36';

    //Private variables
    var showPerc = document.getElementById("elapsedTime");   
    var x = self.canvas.width / 2;
    var y = self.canvas.height / 2;
    var radius = 75;  
    var counterClockwise = false;
    var circ = Math.PI * 2;
    var quart = Math.PI / 2;

    //Methods
    self.animate = function (current) {
        self.context.clearRect(0, 0, self.canvas.width, self.canvas.height);
        self.context.beginPath();
        self.context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
        self.context.stroke();
        self.curPerc++;

        if (self.curPerc < self.endPercent) {
            requestAnimationFrame(function () {
                self.animate(curPerc / 100);
                showPerc.innerHTML = self.curPerc + '%';
            });
        }
    };
}

is starting to head in a better direction.

Autres conseils

I ran into the same problem using three.js while calling requestAnimationFrame from inside an ES6 class method and the way I ended up solving it was by:

animate() {
    requestAnimationFrame(() => this.animate());
    this.render();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top