3

So I've been trying to get an image preloader to work, as I've understood that I need to load the images before I can draw them on the canvas. I've followed this description: How do image preloaders work? but I'm unsure about how to make the img.onload into a method, or somehow make a workaround, as the function can't access the variables it's supposed to.

Here's my code. Canvas class isn't included as it's irrelevant. Thanks in advance.

    window.onload = function () {
        var MyApp = new App();
        MyApp.Initialize();
    }
    class App {
        canvas: Canvas;
        imageURLs: string[] = [];
        images = [];
        imagePreLoader: ImagePreLoader;
        constructor() {
            this.canvas = new Canvas(window.innerWidth, window.innerHeight, "mainCanvas");
            this.ImagePreLoader = new ImagePreLoader(this.imageURLs, this.images);
        }
        Initialize() {
            this.imageURLs.push("0.png");
            this.imageURLs.push("1.png");
            this.imagePreLoader.startLoadingAllImages(this.Loop.bind(this));
        }
        Loop() {
            this.canvas.clear();
            this.Draw();
            requestAnimationFrame(this.Loop.bind(this));
        }
        Draw() {
            for (var i = 0; i < this.images.length; i++) {
                this.canvas.drawImage(this.images[i], i * 100, 100);
            }
        }
    }
    class ImagePreLoader {
        imagesLoaded = 0;
        imageURLs: string[];
        images;
        constructor(urlArray: string[], imageArray) {
            this.imageURLs = urlArray;
            this.images = imageArray;
        }
        startLoadingAllImages(callback): void {
            for (var i = 0; i < this.imageURLs.length; i++) {
                var img = new Image();
                this.images.push(img);
                img.onload = function () { //This doesn't work as the function can't access the variables of the class.
                    this.imagesLoaded++;
                    if (this.imagesLoaded >= this.imageURLs.length) {
                        callback();
                    }
                }
                img.src = this.imageURLs[i];
            }
        }
    }
Community
  • 1
  • 1
Tc_
  • 505
  • 1
  • 6
  • 15

1 Answers1

4

Change :

img.onload = function () { //This doesn't work as the function can't access the variables of the class.
    this.imagesLoaded++;
    if (this.imagesLoaded >= imageURLs.length) {
        callback();
    }
}

to:

img.onload = () => { 
    this.imagesLoaded++;
    if (this.imagesLoaded >= imageURLs.length) {
        callback();
    }
}

using a lambda, i.e. () => { ... }, makes the this keyword work as expected in this situation. A function will get its scope (this) from the caller giving it a faulty scope in this case.

Nypan
  • 6,980
  • 3
  • 21
  • 28